unit U1 — 1 of 4
OAuth2 in practice
auth-code + PKCE, refresh rotation
OAuth2 is how you act on a user's behalf without ever holding their password — the client's Salesforce, Google, or Xero grants your flow a scoped access token instead. For any interactive integration the authorization-code flow is the one you want: the user consents in a browser, the provider hands back a short-lived code, and you swap that code for tokens server-side. Access tokens expire in minutes to an hour by design, so the real work in production is not getting the first token — it is refreshing it forever without a human in the loop.
The engine wires most of this for you: create an OAuth2 Connection, set the auth and token URLs, scopes, and client id/secret, and the built-in flow stores and refreshes the token for you. PKCE hardens the code exchange — you send a code_challenge up front and prove ownership with the code_verifier at swap time, so a stolen code is useless on its own. When you drive the flow by hand in an HTTP Request Piece, you own the token store: persist the refresh token, watch expires_in, and swap early rather than on the 401.
Where it breaks: refresh-token rotation. Many providers issue a brand-new refresh token on every refresh and silently revoke the one you just used; keep reusing the original and the provider reads the replay as a stolen credential, then kills the entire grant. Always persist the new refresh_token from each response, and never let two refreshes race on the same credential at once.
worked example
A client’s flow trading an authorization code for tokens against their Xero tenant, PKCE verifier included.
curl -s -X POST https://identity.acme-books.dev/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=ac_9f2b1e7c \
-d code_verifier=x7Q…redacted…kP0 \
-d redirect_uri=https://hooks.youragency.dev/oauth/callback \
-d client_id=cli_4821 \
-d client_secret=sk-•••
# 200 → { access_token, expires_in: 1800, refresh_token: rt_NEW }
# store rt_NEW, discard the old refresh token, refresh at ~T-120sfield checklist
- Use the authorization-code flow with PKCE for any interactive grant.
- Request the narrowest scopes the integration actually needs.
- Persist the new refresh_token returned by every refresh response.
- Refresh ahead of expiry, not reactively on a 401.
- Store client secrets in a Connection, never in a step parameter.
common failure — Reusing a rotated refresh token
A nightly sync ran fine for weeks, then every run started returning invalid_grant and the integration went dark. The provider rotated refresh tokens on each use, but the flow always replayed the original — read as a stolen credential, so the grant was revoked. Capture refresh_token from each token response, overwrite the stored value, and serialise refreshes so two runs never race.
check your understanding
A nightly sync ran for weeks, then every run began failing and the grant was revoked entirely. The provider rotates credentials on each refresh. Which field must be persisted from every token response?
next unit opens once this is passed
sandbox validation
The check above confirms you followed the unit. Marking the module COMPLETED takes more: build the automation in your own engine and submit the exported flow and its run evidence, signed, to your unique validation URL. See the module page for that spec.