Skip to content

feat(salesforce): PKCE support + userURL configurable#522

Open
phof wants to merge 6 commits into
atinux:mainfrom
phof:sfdc_pkce
Open

feat(salesforce): PKCE support + userURL configurable#522
phof wants to merge 6 commits into
atinux:mainfrom
phof:sfdc_pkce

Conversation

@phof

@phof phof commented May 8, 2026

Copy link
Copy Markdown
Contributor
  • Adds PKCE support
  • Makes the userURL configurable

Summary by CodeRabbit

  • New Features
    • Added PKCE (Proof Key for Code Exchange) support for Salesforce OAuth to strengthen authentication security.
    • Made the Salesforce user-info endpoint configurable and improved base-URL resolution for more flexible OAuth configuration.

@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ead304d-a373-4e4a-bfc7-14d1d820b476

📥 Commits

Reviewing files that changed from the base of the PR and between 3f2a6ea and 8597dc3.

📒 Files selected for processing (1)
  • src/runtime/server/lib/oauth/salesforce.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/runtime/server/lib/oauth/salesforce.ts

📝 Walkthrough

Walkthrough

Salesforce OAuth handler: adds PKCE (verifier/challenge), includes PKCE params on authorization redirect, sends code_verifier during token exchange, introduces configurable userURL, and resolves baseURL from runtime config when missing.

Changes

Salesforce OAuth PKCE Enhancement

Layer / File(s) Summary
Configuration Contract
src/runtime/server/lib/oauth/salesforce.ts
OAuthSalesforceConfig interface extended with optional userURL property for configurable user-info endpoint.
Utility Imports
src/runtime/server/lib/oauth/salesforce.ts
Imports updated to include PKCE helper (handlePkceVerifier).
Configuration Defaults
src/runtime/server/lib/oauth/salesforce.ts
baseURL resolution now falls back to runtimeConfig.baseURL; default authorizationURL, tokenURL, and userURL derive from the resolved baseURL.
PKCE Preparation
src/runtime/server/lib/oauth/salesforce.ts
PKCE verifier and code_challenge are generated before the authorization redirect.
Authorization Redirect
src/runtime/server/lib/oauth/salesforce.ts
code_challenge and code_challenge_method added to the authorization redirect query.
Token Exchange
src/runtime/server/lib/oauth/salesforce.ts
code_verifier included in token exchange request body when exchanging the authorization code for tokens.
User-Info Fetch
src/runtime/server/lib/oauth/salesforce.ts
User-info requested from config.userURL instead of being constructed from baseURL.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SalesforceHandler
  participant SalesforceAuthZ as Salesforce AuthZ
  participant SalesforceAPI as Salesforce API
  Client->>SalesforceHandler: Initiate login
  SalesforceHandler->>SalesforceHandler: Generate PKCE verifier & code_challenge
  SalesforceHandler->>Client: Redirect to Salesforce AuthZ (includes code_challenge)
  Client->>SalesforceAuthZ: Authorize
  SalesforceAuthZ-->>Client: Authorization code
  Client->>SalesforceHandler: Callback with code
  SalesforceHandler->>SalesforceAPI: Exchange code + code_verifier
  SalesforceAPI-->>SalesforceHandler: Access token
  SalesforceHandler->>SalesforceAPI: GET config.userURL
  SalesforceAPI-->>SalesforceHandler: User info
  SalesforceHandler-->>Client: Session created
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through code to add PKCE bloom,
Verifier hidden, challenge in tune,
User-info freed from hardcoded place,
Now auth dances with a safer pace,
Hooray — secure logins make me swoon!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately summarizes the two main changes: PKCE support addition and userURL configuration, matching the file-level summaries and PR objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Comment @coderabbitai help to get the list of available commands and usage tips.

@phof phof changed the title feat(salesforce): make userURL configurable feat(salesforce): PKCE support + userURL configurable May 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/runtime/server/lib/oauth/salesforce.ts (2)

98-106: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Prevent authorizationParams from overriding generated state and PKCE values.

Because ...config.authorizationParams is spread last here, a consumer can clobber state, code_challenge, or code_challenge_method. That either weakens the CSRF/PKCE guarantees or causes the later code_verifier exchange to fail.

Suggested fix
       return sendRedirect(
         event,
         withQuery(config.authorizationURL as string, {
+          ...config.authorizationParams,
           response_type: 'code',
           client_id: config.clientId,
           redirect_uri: redirectURL,
           scope: config.scope.join(' '),
           state,
           code_challenge: pkce.code_challenge,
           code_challenge_method: pkce.code_challenge_method,
-          ...config.authorizationParams,
         }),
       )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/server/lib/oauth/salesforce.ts` around lines 98 - 106, The
authorizationParams spread currently comes last in the withQuery call and can
override the generated state and PKCE values; update the call in withQuery so
that config.authorizationParams is either spread before the explicit keys
(response_type, client_id, redirect_uri, scope, state, code_challenge,
code_challenge_method) or filter out keys
["state","code_challenge","code_challenge_method"] from
config.authorizationParams before spreading, ensuring the generated state and
pkce (pkce.code_challenge, pkce.code_challenge_method) remain authoritative and
that the subsequent code_verifier exchange will succeed.

65-72: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Derive the default endpoints from the merged baseURL.

Line 66 only reads config?.baseURL, so deployments that set oauth.salesforce.baseURL via runtime config still default authorizationURL, tokenURL, and the new userURL to https://login.salesforce.com. That breaks My Domain setups unless callers redundantly override every URL.

Suggested fix
   const runtimeConfig = useRuntimeConfig(event).oauth?.salesforce
-  const baseURL = config?.baseURL || 'https://login.salesforce.com'
+  const baseURL = config?.baseURL || runtimeConfig?.baseURL || 'https://login.salesforce.com'
   config = defu(config, runtimeConfig, {
     authorizationURL: `${baseURL}/services/oauth2/authorize`,
     tokenURL: `${baseURL}/services/oauth2/token`,
     userURL: `${baseURL}/services/oauth2/userinfo`,
     authorizationParams: {},
   }) as OAuthSalesforceConfig
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/server/lib/oauth/salesforce.ts` around lines 65 - 72, The current
code uses only config?.baseURL to build default endpoints so runtime-provided
oauth.salesforce.baseURL is ignored; fix by first merging config and
runtimeConfig (ensuring a default baseURL of 'https://login.salesforce.com') and
then derive authorizationURL, tokenURL and userURL from the merged baseURL.
Concretely: use useRuntimeConfig to get runtimeConfig, defu(config,
runtimeConfig, { baseURL: 'https://login.salesforce.com' }) to produce a merged
config, read baseURL from that merged config, then defu again to set
authorizationURL, tokenURL, userURL and authorizationParams using
`${baseURL}/services/oauth2/...`; keep types like OAuthSalesforceConfig
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/runtime/server/lib/oauth/salesforce.ts`:
- Around line 98-106: The authorizationParams spread currently comes last in the
withQuery call and can override the generated state and PKCE values; update the
call in withQuery so that config.authorizationParams is either spread before the
explicit keys (response_type, client_id, redirect_uri, scope, state,
code_challenge, code_challenge_method) or filter out keys
["state","code_challenge","code_challenge_method"] from
config.authorizationParams before spreading, ensuring the generated state and
pkce (pkce.code_challenge, pkce.code_challenge_method) remain authoritative and
that the subsequent code_verifier exchange will succeed.
- Around line 65-72: The current code uses only config?.baseURL to build default
endpoints so runtime-provided oauth.salesforce.baseURL is ignored; fix by first
merging config and runtimeConfig (ensuring a default baseURL of
'https://login.salesforce.com') and then derive authorizationURL, tokenURL and
userURL from the merged baseURL. Concretely: use useRuntimeConfig to get
runtimeConfig, defu(config, runtimeConfig, { baseURL:
'https://login.salesforce.com' }) to produce a merged config, read baseURL from
that merged config, then defu again to set authorizationURL, tokenURL, userURL
and authorizationParams using `${baseURL}/services/oauth2/...`; keep types like
OAuthSalesforceConfig unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b50a37b5-ab10-4189-bfc9-03ba6d4cbb27

📥 Commits

Reviewing files that changed from the base of the PR and between ceb366b and 48f7ddd.

📒 Files selected for processing (1)
  • src/runtime/server/lib/oauth/salesforce.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/runtime/server/lib/oauth/salesforce.ts (1)

98-107: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't let authorizationParams override core OAuth params.

authorizationParams can still replace client_id, redirect_uri, response_type, or scope. If redirect_uri or client_id is overridden here, the authorize request and the token exchange will use different values, and the code exchange will fail.

Suggested fix
       return sendRedirect(
         event,
         withQuery(config.authorizationURL as string, {
+          ...config.authorizationParams,
           response_type: 'code',
           client_id: config.clientId,
           redirect_uri: redirectURL,
           scope: config.scope.join(' '),
-          ...config.authorizationParams,
           code_challenge: pkce.code_challenge,
           code_challenge_method: pkce.code_challenge_method,
           state,
         }),
       )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/runtime/server/lib/oauth/salesforce.ts` around lines 98 - 107, The
authorize URL construction using withQuery currently spreads
config.authorizationParams after the core params, allowing authorizationParams
to override critical OAuth fields (response_type, client_id, redirect_uri,
scope, code_challenge, code_challenge_method, state); change the order so core
params (response_type, client_id, redirect_uri, scope, code_challenge,
code_challenge_method, state, and any other required fields) are spread last or
explicitly override any conflicting keys from config.authorizationParams to
ensure withQuery and the function that performs the token exchange use the same
client_id and redirect_uri; update the call site in the salesforce OAuth flow
(the withQuery invocation) to either filter out these keys from
config.authorizationParams or apply config.authorizationParams first and then
apply the core params to guarantee they cannot be replaced.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/runtime/server/lib/oauth/salesforce.ts`:
- Around line 42-46: The JSDoc for the userURL option is incorrect: update the
comment on userURL to state that it is derived from the resolved baseURL (not a
fixed https://login.salesforce.com value) and that it will follow any My Domain
or baseURL override; mention the relationship to baseURL and where the
resolution occurs (the code that computes userURL from baseURL) so readers know
overriding baseURL changes userURL accordingly.

---

Outside diff comments:
In `@src/runtime/server/lib/oauth/salesforce.ts`:
- Around line 98-107: The authorize URL construction using withQuery currently
spreads config.authorizationParams after the core params, allowing
authorizationParams to override critical OAuth fields (response_type, client_id,
redirect_uri, scope, code_challenge, code_challenge_method, state); change the
order so core params (response_type, client_id, redirect_uri, scope,
code_challenge, code_challenge_method, state, and any other required fields) are
spread last or explicitly override any conflicting keys from
config.authorizationParams to ensure withQuery and the function that performs
the token exchange use the same client_id and redirect_uri; update the call site
in the salesforce OAuth flow (the withQuery invocation) to either filter out
these keys from config.authorizationParams or apply config.authorizationParams
first and then apply the core params to guarantee they cannot be replaced.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f5dc8a9d-0b40-4a69-a5d0-cc9205de92d3

📥 Commits

Reviewing files that changed from the base of the PR and between 48f7ddd and 3f2a6ea.

📒 Files selected for processing (1)
  • src/runtime/server/lib/oauth/salesforce.ts

Comment thread src/runtime/server/lib/oauth/salesforce.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant