We recently built a GetGoogleCalendarEvents invocable action to enable a fun and useful Alerter app based on Flow. To enable a flow to retrieve Google calendar events from a flow, it’s necessary to create a authenticated Named Credential in your org. Here’s an updated walkthrough on how to do that.
Thanks are due to this great article on authentication by Piotr Gajek, which was critical in enabling me to figure things out.
Step 1: Generating a Client ID and Client Secret on the target non-Salesforce web service
To retrieve calendar events from Google, we start by logging into Google Cloud Platform and generating some credentials that we can use to make API calls into Google using our Google account.
When we generate what Google calls an ‘OAuth 2.0 Client ID’, we’re given a client ID and client secret provided by Google.
Here’s my Google Cloud Platform credentials page where I’ve created a Client ID:
When I click on it for details, I can access both the client Id and client Secret:
Each web service will have a slightly different process, but they all will end up generating a Client ID and Client Secret (note: a few services, like AWS, have additional or different security protocols).
The next step is to take this identifying information and add it to our Salesforce org via an Auth. Provider.
Step 2: Creating the Auth. Provider for the target Web Service
Each time you want to enable a particular service and service configuration to be called programmatically from your Salesforce org, you need to create an Auth. Provider. Now, Auth. Provider is a pretty unfriendly name. I would have gone with something like ‘Web Service Access Definition’. You create one on your org to tell Salesforce that properly permissioned Users on your org are allowed to connect to the non-Salesforce web site via its apis. You can set up different Auth. Providers that connect to the same non-Salesforce web service but provide different amounts of access, and then assign usage rights to different permissions sets or profiles.
2.1 Select the Provider Type
There are different types of Auth.Providers. Each type represents a different style of authentication. Take a look at the list of available types:
A few of these, like the Apple authentication protocol, are truly unique, but most of these look very similar because they’re all basically using the OAuth industry standard. The most general purpose provider type is Open ID Connect, which is the general purpose solution that works for almost all web services. That’s the one we’ll use for our Auth. Provider. (Why not use the Google Auth Provider type? You’d think it would be more fitting for a Google connection. However it turns out to require some extra fiddly work to get it to work properly. You need to add an extra openId scope in and you need to override the authorization URL to enable refresh tokens. Ultimately, it’s more pain than its worth. Also, the process shown here for Open ID Connect will work smoothly with other web services besides Google. So we’ll use the general purpose solution)
After selecting provider type, fill in the client ID and secret fields.
2.2 Providing Authorization URLs
Automatic authorization between two sites requires them to have a conversation with each other via URLs, so you need to specify the right URLs for them to use.
The required fields are Authorize Endpoint URL and Token Endpoint URL. In our case, because we’re calling from Salesforce to Google, these are going to be Google URLs. The first one will be used to start the authorization process and the second one will be used to get tokens.
These URLs are generally found near where you generated your client ID and secret. However, with Google, there were some oddities. Google no longer provides clear documentation for setting up an oAuth session directly, instead recommending that you use a higher level client library:
Google’s concern is laudable, but that doesn’t help us Salesforce users much, as we still need to determine the low-level URL’s to configure our Auth. Provider. To solve this, I had to dig up this good article by Piotr Gajek.
Here are the URL’s that you need to use:
Authorize Endpoint URL: https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force
Token Endpoint URL: https://oauth2.googleapis.com/token
A Few Notes on Automatic Token Refresh
- Google’s tokens only last 1 hour, so you can only deploy something useful to production if you add automatic token refresh. This is done by adding ‘access_type=offline&approval_prompt=force’ to the authorization URL, as shown above. (More on that here and here)
- Another troubleshooting note: In my own experience, the v1 version of Google’s authorization endpoint, which is shown above, correctly enables automatic token refresh:
…but the extremely similar v2 version authenticates but doesn’t successfully enable automatic refresh.
The Google docs will tend to steer you towards the more recent version, but keep these points in mind.
2.3 Setting the Scopes
The Default Scopes field is used to specify which parts of the target web service are accessible to this authentication provider. I actually set these when I generated the credentials on the google site. Here they are:
Associating some specific scopes over on my Google account is only the first part. In order to enable my Salesforce app to access my calendar, I need to similarly add these scopes to the Auth. Provider I’m creating in my org and the Named Credentials that I’ll be using.
I choose to go with these credentials:
for my scopes. I could alternatively reduce the scope down to show only free/busy information:
2.4 Completing the Auth Provider Creation
Here’s what my configured Auth. Provider looks like
3. Locate the Org-Specific Callback URL and Provide It To Google
When actual authentication happens, you start in Salesforce and get a pop up that lets you log into Google. You’ve done this ‘OAuth dance’ hundreds of times, most likely. This forces you to actually log in properly to Google which makes Google comfortable enough to trust future API calls. At the end of this dance, Google needs to send you back to Salesforce. This is done via the ‘Callback URL’ (or sometimes ‘Redirect URL). Each Salesforce org has a different base URL so each of your orgs will have its own unique Callback URL, and you need to let Google know what it is. So we collect it here, from our Auth. Provider:
…and paste it into the Google authorization here:
4. Creating a Named Credential for our Callouts
We also need to create a Named Credential, and at this point a lot of people (including myself, routinely) start to struggle to distinguish all of these abstract objects.
Why shouldn’t we be able to simply assign to a permission set the ability to use the Auth Provider? My layman’s explanation, which is unquestionably not the most technically precise answer, is that organizations generally want a way to create authorizations that provide access to some of a service but not all of a service. It’s true that we focused down the reach of this authorization via scopes, but you might want to limit things further. The Named Credential sits on top of the Auth. Provider and provides a complete authorization and authentication package that can be associated with Permission Sets. One key element of Named Credentials is the endpoint URL that the Credential is authorized to call. Usually these URLS represent API endpoints. Notice that until now, the only URL’s that we’ve been using have been special authentication URLs with words like ‘auth’ and ‘token’. But when I call the Google Calendar API, I’m going to call an endpoint designed for general calls. For Google Calendar, the endpoint is https://www.googleapis.com, and the rest of the URL is /calendar/v3/calendars/[mycalendarid]/events. You find these URL’s in the API documentation of your target web service.
And if you look in the Permission Set section, you’ll see a specific section where you can associate Named Credential with a permission set:
Here’s my configured Named Credential:
Note that I again provide the scopes that I want my action to have access to, and that I select the Auth Provider that I created above.
The URL provided here is the main URL for calling the Google API, and this is therefore is the only URL this credential will be able to call.
5. Authenticate to your Google Account From Salesforce
That final checkbox ‘Start Authentication Flow on Save’ is important because, even though I’ve copied my Google id and secret into my org, that’s not enough to get Google to trust API calls from my org. I have to do an actual authentication, and the final checkbox causes it to start. Here’s the first thing you’ll see:
Once you successfully connect to the Google account linked to this particular client ID and secret, your Named Credential will show ‘Authenticated’ and you can now use it in your callouts:
Remember above where we talked briefly about refresh tokens? If you don’t include those extra parameters on your authorization call, you’ll succeed, but you’ll get this warning, and you can expect your token to expire after a brief period of time:
6. Using Your Named Credential With a Flow Action
Actions that make web callouts will generally have an input for a token of some sort. Here, it’s labelled ‘credName’ to emphasize that what we want is the name of a Named Credential:
Not all callout actions support Named Credentials, however. For this action that retrieves weather, the api token doesn’t expire and is easily generated without oAuth, so the action simply asks for it:
And that’s all that has to be done. As you can see, if you have access to use a Named Credential, you have the ability make calls. When I run this action, I get back Calendar events:
And that’s the story on authenticating with Auth. Providers and Named Credentials.
Callouts are represented in URLs by the prefix ‘callout:’. You generally connect a Named Credential to an action by passing in the name of the action. You incorporate the name of the Named Credential into the URL of your API call, and Salesforce handles the incorporation of necessary elements into the actual API call. In our case, with Google Calendar, the API expects a token to be provided in the header of the API call. This is the most common approach. If you were bypassing Named Credentials, you’d manually insert the token into your call like this:
When we use a named credential, Salesforce handles that for us. Here’s how it looks: