Skip to content

Add PKCE, richer user info, and Slack OAuth V2 fields#5

Open
poudelprakash wants to merge 1 commit into
mainfrom
features/enhance-slack-strategy
Open

Add PKCE, richer user info, and Slack OAuth V2 fields#5
poudelprakash wants to merge 1 commit into
mainfrom
features/enhance-slack-strategy

Conversation

@poudelprakash
Copy link
Copy Markdown
Member

@poudelprakash poudelprakash commented Apr 18, 2026

Summary

  • PKCE: Enabled by default for improved OAuth security
  • team authorize option: Allows pre-selecting a workspace on the authorize URL
  • Enterprise Grid: Exposes enterprise_info (org id/name) in extra hash
  • Incoming webhook: Exposes incoming_webhook data (channel, url, etc.) in extra hash
  • Bot user ID: Exposes bot_user_id in extra hash for bot token identification
  • Granted scopes: Exposes scope and authed_user_scope in extra hash
  • Richer user info: Adds title, phone, status_text, status_emoji, image_192, image_512, image_original, tz, tz_offset, is_admin, is_owner to info hash

All new fields are additive — they return nil when not present, so there are no breaking changes.

Test plan

  • All 17 existing tests still pass (no regressions)
  • 16 new tests added (33 total), all passing
  • Rubocop: 0 offenses
  • Verified on Ruby 4.0.2
  • Integration test with a real Slack app (manual)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • PKCE is now enabled for Slack OAuth authentication.
    • Team parameter is now supported in authorization requests.
    • User profile data now includes additional image sizes, profile metadata (title, phone, status), timezone information, and admin/owner status flags.
    • Expanded profile data includes enterprise information, incoming webhook details, and authorization scopes.
  • Tests

    • Added comprehensive test coverage for Slack OAuth strategy configuration and profile data handling.

- Enable PKCE by default for improved security
- Add `team` to authorize_options to allow workspace pre-selection
- Expose enterprise info (Enterprise Grid org-level installs)
- Expose incoming webhook data (channel, url, etc.)
- Expose bot_user_id for bot token identification
- Expose granted scopes (scope and authed_user scope)
- Add richer user info: title, phone, status, timezone, image sizes,
  admin/owner flags
- All new fields are additive (nil when absent), no breaking changes
- Tests: 17 → 33 examples, all passing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 18, 2026

📝 Walkthrough

Walkthrough

These changes enhance the Slack OAuth strategy by expanding authorization parameters to include team, enabling PKCE, and enriching both info and extra output with additional user profile metadata and OAuth parameters. Supporting RuboCop configuration updates accommodate these modifications.

Changes

Cohort / File(s) Summary
RuboCop Configuration
.rubocop.yml
Increased Metrics/ClassLength threshold from 150 to 170 and added Naming/VariableNumber cop with snake_case enforcement and allowlist for image-sized variables (image_192, image_512, image_48).
Slack Strategy Implementation
lib/omniauth/strategies/slack.rb
Added team to authorized options, enabled PKCE, enhanced info hash with safer nil-handling for user identity and expanded profile fields (multiple image sizes, title, phone, status, timezone, admin/owner flags), and extended extra hash with conditional exposure of enterprise info, incoming webhook, bot user ID, and scope parameters.
Slack Strategy Tests
spec/omniauth/strategies/slack_spec.rb
Added comprehensive test coverage for default PKCE configuration, team in authorize options, conditional inclusion/exclusion of extra fields based on access token parameters, and info field presence/absence scenarios across user metadata and profile details.

Sequence Diagram

sequenceDiagram
    participant User
    participant Client as Slack OAuth Client
    participant Strategy as OmniAuth Slack Strategy
    participant SlackAPI as Slack API
    participant AccessToken as Access Token

    User->>Client: Initiate Login with 'team' parameter
    Client->>Strategy: Request Authorization
    Strategy->>Strategy: Apply PKCE
    Strategy->>SlackAPI: Authorize with team + user_scope + scope + PKCE
    SlackAPI-->>Strategy: Return authorization code
    Strategy->>SlackAPI: Exchange code for tokens
    SlackAPI-->>AccessToken: Return tokens & params
    Strategy->>Strategy: Extract info (user identity, profile fields)
    Strategy->>Strategy: Extract extra (conditional OAuth metadata)
    Strategy-->>Client: Return profile (info) + metadata (extra)
    Client-->>User: Login complete
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A Slack strategy so refined,
With PKCE and team in mind,
More fields dance in info's glow,
Extra metadata starts to flow,
OAuth enhanced, secure and bright! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the three main changes: enabling PKCE, expanding user info fields, and adding Slack OAuth V2 fields.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch features/enhance-slack-strategy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/omniauth/strategies/slack.rb`:
- Line 12: The change enabling PKCE by default (the line `option :pkce, true` in
the Slack OmniAuth strategy) is a breaking change; revert this default and
instead document and gate PKCE behind an explicit opt-in (e.g., keep `option
:pkce` unset or false and allow app code to enable it), and add an end-to-end
spec exercising the full authorize + callback flow with PKCE parameters
(generate code_verifier/code_challenge, include code_challenge_method, and
assert successful callback) plus a real Slack app integration test before
flipping the default; update the strategy tests to cover both non-PKCE and PKCE
paths so enabling later is safe.
- Line 55: Replace the direct assignment of the incoming_webhook into the auth
hash so the webhook URL is redacted: when setting hash["incoming_webhook"] from
access_token.params["incoming_webhook"], copy the object but replace or remove
the "url" key (e.g. set "url" => "[REDACTED]") before assigning to hash; update
the corresponding spec for the Slack strategy to expect the redacted
incoming_webhook.url value instead of the real URL.
🪄 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

Run ID: c239afbc-86a4-4f6d-bfb6-c081388fce22

📥 Commits

Reviewing files that changed from the base of the PR and between 77a78b5 and 90380c7.

📒 Files selected for processing (3)
  • .rubocop.yml
  • lib/omniauth/strategies/slack.rb
  • spec/omniauth/strategies/slack_spec.rb

option :authorize_options, %i[user_scope scope]
option :authorize_options, %i[user_scope scope team]

option :pkce, true
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does Slack OAuth V2 support PKCE code_challenge and code_verifier for /oauth/v2/authorize and /api/oauth.v2.access?

💡 Result:

Yes, Slack OAuth V2 supports PKCE code_challenge and code_verifier for both /oauth/v2/authorize and /api/oauth.v2.access. PKCE became generally available on March 30, 2026. It must be enabled in the app settings (one-way operation marking the app as a public client). Once enabled: - For /oauth/v2/authorize: Append code_challenge, code_challenge_method=S256 (SHA-256 only), and optionally code_verifier arguments to the authorization URL. Required for custom URI schemes; optional otherwise. - For /api/oauth.v2.access: Include code_verifier (optional if client_secret provided, but used without client_secret for public clients). Do not send client_secret. Official docs confirm code_verifier as an optional parameter in oauth.v2.access, with examples and error handling for invalid code_verifier.

Citations:


🌐 Web query:

How does omniauth-oauth2 implement option :pkce, true, and which gem versions support it?

💡 Result:

Omniauth-oauth2 implements the :pkce, true option by adding PKCE (Proof Key for Code Exchange) support to the OAuth2 authorization code grant flow, as per RFC 7636. When enabled via option :pkce, true in the strategy configuration, it performs the following: 1. In authorize_params (called during the authorization request phase): - Generates a random code_verifier (SecureRandom.hex(64), 128 characters, meeting the 43-128 requirement). - Computes code_challenge as Base64.urlsafe_encode64(Digest::SHA2.digest(verifier), padding: false). - Adds code_challenge and code_challenge_method: 'S256' to the authorize URL query parameters. - Stores the code_verifier in the session under "omniauth.pkce.verifier". 2. In token_params (called during the callback/token exchange phase): - Retrieves the code_verifier from the session (and deletes it). - Adds code_verifier to the token request parameters. This proves possession of the verifier to the provider, preventing authorization code interception attacks. Customizable via :pkce_options for code_challenge proc and method (defaults to S256 SHA256). The feature was added in PR #131 (merged Aug 11, 2020) and first released in v1.7.0 (Aug 11, 2020). All subsequent versions (up to latest v1.9.0, Dec 2025) support it. Versions prior to 1.7.0 do not. Source code is visible in lib/omniauth/strategies/oauth2.rb methods: pkce_authorize_params, pkce_token_params, and integration in authorize_params/token_params. Usage example: provider :my_strategy, 'client_id', 'client_secret', pkce: true

Citations:


Add end-to-end PKCE testing before enabling by default.

While Slack OAuth V2 and omniauth-oauth2 both support PKCE (since March 30, 2026 and v1.7.0 respectively), enabling option :pkce, true by default is a breaking change: it requires all Slack apps to have PKCE explicitly enabled in their settings, but most existing apps do not. Without explicit opt-in, this will fail authentication for unconfigured consumers. Add an end-to-end strategy spec covering authorize + callback with PKCE params, or complete the real Slack app integration test before release to validate the flow works as expected.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/omniauth/strategies/slack.rb` at line 12, The change enabling PKCE by
default (the line `option :pkce, true` in the Slack OmniAuth strategy) is a
breaking change; revert this default and instead document and gate PKCE behind
an explicit opt-in (e.g., keep `option :pkce` unset or false and allow app code
to enable it), and add an end-to-end spec exercising the full authorize +
callback flow with PKCE parameters (generate code_verifier/code_challenge,
include code_challenge_method, and assert successful callback) plus a real Slack
app integration test before flipping the default; update the strategy tests to
cover both non-PKCE and PKCE paths so enabling later is safe.

hash["bot_info"] = bot_info if bot_access_token?
hash["authed_user"] = authed_user_info if authed_user_token?
hash["enterprise_info"] = access_token.params["enterprise"] if access_token.params["enterprise"]
hash["incoming_webhook"] = access_token.params["incoming_webhook"] if access_token.params["incoming_webhook"]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Slack incoming webhook URL secret don't share documentation

💡 Result:

Slack's official documentation explicitly warns that incoming webhook URLs contain a secret token and must be kept confidential. The key guidance is: "Keep it secret, keep it safe. Your webhook URL contains a secret. Don't share it online, including via public version control repositories. Slack actively searches out and revokes leaked secrets." This is stated directly in the primary documentation for sending messages using incoming webhooks. Sharing the URL allows anyone to post messages to the specific Slack channel it's configured for, as authentication relies solely on the URL's secrecy (no additional signatures or keys for incoming webhooks). Best practices from official sources and supporting references: - Store URLs in environment variables or secrets managers, never hardcode in code or commit to repos. - Use separate URLs for dev/staging/prod. - Rotate periodically by generating new ones. - If leaked, revoke via app settings (remove the webhook) and create a new one. Official docs note that while channel-specific (limits some risks), exposure still enables spam/phishing to that channel.

Citations:


🏁 Script executed:

fd -t f -name "slack.rb" | head -20

Repository: TruemarkDev/omniauth-slack

Length of output: 300


🏁 Script executed:

fd -t f -name "slack.rb"

Repository: TruemarkDev/omniauth-slack

Length of output: 300


🏁 Script executed:

git ls-files | grep slack.rb

Repository: TruemarkDev/omniauth-slack

Length of output: 124


🏁 Script executed:

cat -n lib/omniauth/strategies/slack.rb | head -80

Repository: TruemarkDev/omniauth-slack

Length of output: 3423


🏁 Script executed:

cat -n lib/omniauth/strategies/slack.rb | tail -20

Repository: TruemarkDev/omniauth-slack

Length of output: 646


🏁 Script executed:

git ls-files | grep -E "(test|spec)" | head -20

Repository: TruemarkDev/omniauth-slack

Length of output: 146


🏁 Script executed:

cat -n spec/omniauth/strategies/slack_spec.rb | head -150

Repository: TruemarkDev/omniauth-slack

Length of output: 5443


🏁 Script executed:

cat -n spec/omniauth/strategies/slack_spec.rb | grep -A 20 -B 5 "incoming_webhook"

Repository: TruemarkDev/omniauth-slack

Length of output: 2052


Redact the webhook URL from extra metadata to prevent accidental exposure.

The incoming_webhook.url is a credential—anyone with it can post to the Slack channel. The current code exposes the entire webhook object in extra, which is part of the OmniAuth auth hash and risks being logged or stored. The url field must be redacted.

Suggested fix
-        hash["incoming_webhook"] = access_token.params["incoming_webhook"] if access_token.params["incoming_webhook"]
+        if access_token.params["incoming_webhook"]
+          hash["incoming_webhook"] = access_token.params["incoming_webhook"].reject { |key, _| key == "url" }
+        end

The test at spec/omniauth/strategies/slack_spec.rb:207 will also need updating to expect the redacted object.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
hash["incoming_webhook"] = access_token.params["incoming_webhook"] if access_token.params["incoming_webhook"]
if access_token.params["incoming_webhook"]
hash["incoming_webhook"] = access_token.params["incoming_webhook"].reject { |key, _| key == "url" }
end
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/omniauth/strategies/slack.rb` at line 55, Replace the direct assignment
of the incoming_webhook into the auth hash so the webhook URL is redacted: when
setting hash["incoming_webhook"] from access_token.params["incoming_webhook"],
copy the object but replace or remove the "url" key (e.g. set "url" =>
"[REDACTED]") before assigning to hash; update the corresponding spec for the
Slack strategy to expect the redacted incoming_webhook.url value instead of the
real URL.

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