The Pickup Word
Module 3 of 5 in the chapter The Burger House: Flows With a Person, chapter 9 of Securing Salesforce: Identity and Access. Each module stands on its own.
The question this module answers: What was the web server flow’s weakness, and how does PKCE close it?
The weakness
Section titled “The weakness”Get the web server flow down first; then I’ll show you its weakness, and how it was fixed.
The weakness is this little code. In step 3, Salesforce hands the code to Priya’s browser, and her browser hands it to the Burger House. For a moment, milliseconds to a few seconds, the code is sitting in her browser before the Burger House presents it.
And what could a bad actor do with it, if they caught it in that moment? Present it themselves, and swap it for a token. That’s what people found a way to do. Picture it at the festival’s counter: you get your claim ticket for your drink, you turn toward the cash register, and somebody grabs the ticket out of your hand, runs to the register, and gets your drink first. They beat you there.
Module 1 said the swap also needs the Burger House’s secret. That protects a server-side app. But an app that runs on a phone or in a browser can’t keep a secret: Salesforce puts it plainly, “the client secret is accessible and exploitable because client executables reside on the user’s device” (S9). And even with a secret, the code was the one thing in the browser that could be stolen. We needed a way to lock the code to the Burger House, so nobody else could use it.
The pickup word
Section titled “The pickup word”The fix is called PKCE, Proof Key for Code Exchange, pronounced “pixy”. Integration Architect gives it a picture, and this course uses the same one.
Before the Burger House sends Priya to Salesforce, it writes a pickup word on a slip of paper and keeps the slip. It sends Salesforce only the word’s fingerprint. Salesforce keeps the fingerprint with her request.
When the Burger House comes back to swap the code, it has to show the slip. Salesforce checks that the word matches the fingerprint. Only then does it hand over the tokens.
Now go back to the cash register. The thief grabbed the claim ticket, the code. But they don’t have the slip. They show up with the code and no pickup word, and they get nothing. The one that asked at the beginning has to be the same one that comes back at the end.
On the wire
Section titled “On the wire”It’s just a couple of extra lines (S1):
| In the request | What it is | |
|---|---|---|
| The pickup word | code_verifier, in the token request (step 4) | “128 bytes of random data with high entropy”, made fresh each time |
| Its fingerprint | code_challenge, in the authorize request (step 2) | “the SHA256 hash value of the code_verifier”, base64url-encoded |
So the authorize request from module 2 gains one line:
code_challenge=*******************And the token request gains another:
code_verifier=*******************If they don’t match, Salesforce refuses: the login “fails with the invalid_grant error code” (S1).
Why a fingerprint works
Section titled “Why a fingerprint works”Why is it safe to send the fingerprint through the browser, where anyone might see it? Because a fingerprint is a hash, from chapter 3. You can make the hash from the word in an instant, but you can’t run it backwards. Hashes are one-way. Seeing the fingerprint tells you nothing about the word, so the slip stays secret even though its fingerprint has travelled through the front channel.
Not optional any more
Section titled “Not optional any more”For years PKCE was an option. Now:
- New apps need it. From July 2026, Salesforce requires PKCE for the authorization code grant on new external client apps and connected apps, turned on for every new app from August 2026 (S3).
- ISV apps need it. “The use of PKCE to protect OAuth Authorization Code login flows is now required for all ISV Salesforce client apps… it is now considered an essential industry security practice for OAuth 2.0” (S2).
- An org can require it for every app. In Setup, OAuth and OpenID Connect Settings, turn on Require Proof Key for Code Exchange (PKCE) (S2).
For an existing app, there’s an order to it. Salesforce’s caution: “enabling PKCE requires a coordinated change on both the server and clients” (S2). Change the app’s code to send the challenge and verifier first, then require PKCE on the app in Salesforce, and only when every app is done, turn on the org-wide setting. Do it the other way round, and the apps stop working. Test it in a sandbox first.
Test knowledge. In my experience, know what PKCE protects against (a stolen authorization code), which value goes where (the challenge in the authorize request, the verifier in the token request), and that the challenge is a hash of the verifier.
What’s next
Section titled “What’s next”Module 4: who is she? OpenID Connect.
What an architect decides here
Section titled “What an architect decides here”- PKCE on every app that uses the web server flow, new or old.
- The order of the change for existing apps: the app’s code, then the app’s setting, then the org.
- When to turn on Require PKCE for the whole org.
Explore
Section titled “Explore”- OAuth 2.0 Web Server Flow for Web App Integration (opens in a new tab) (Salesforce Help, Winter ‘27; checked 2026-11-07)
- Enabling PKCE for OAuth for Salesforce External Client and Connected Apps (opens in a new tab) (Salesforce Help, published September 22, 2026; checked 2026-11-07)
