Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth redirect URI blank #2449

Open
jfbn opened this issue Mar 10, 2025 · 5 comments
Open

OAuth redirect URI blank #2449

jfbn opened this issue Mar 10, 2025 · 5 comments
Labels
question M-T: User needs support to use the project

Comments

@jfbn
Copy link

jfbn commented Mar 10, 2025

I'm creating an ExpressReceiver like so:

const receiver = new ExpressReceiver({
  signingSecret,
  clientId,
  clientSecret,
  stateSecret,
  scopes: ['chat:write'],
  // redirectUri: 'https://localhost:3000/slack/oauth_redirect',
  installerOptions: {
    directInstall: true,
    // redirectUriPath: '/slack/oauth_redirect',
    callbackOptions: {
      success: async (installation, installOptions, req, res) => {
        console.log('success installation', installation)
      },
      failure: async (error, installOptions, req, res) => {
        console.error('Failed to install app', error)
      },
    },
  },
  installationStore: new FileInstallationStore(),
})

When going to the install route (/slack/install), I am correctly forwarded to the Workspace related page to grant permissions.
However the redirect_uri query param is empty (redirect_uri=).

I don't understand if this is intentional or not, as the documentation reads:

Bolt for JavaScript provides the Redirect URL path /slack/oauth_redirect out-of-the-box for Slack to use when redirecting users that complete the OAuth installation flow.

It works as expected if I uncomment the 2 lines in my example.

Should the default redirect uri be part of the query string if omitted from the config?

@jfbn jfbn added the untriaged label Mar 10, 2025
@zimeg zimeg added question M-T: User needs support to use the project needs info An issue that is claimed to be a bug and hasn't been reproduced, or otherwise needs more info and removed untriaged labels Mar 10, 2025
@zimeg
Copy link
Member

zimeg commented Mar 10, 2025

Hey @jfbn! 👋 Thanks for sharing this code snippet and question.

The setup you have seems to be working for me after checking for matching and saved Redirect URLs on app settings under the OAuth & Permissions tab 🔍

However the redirect_uri query param is empty (redirect_uri=).

I noticed this too and it caught me off guard... However, I believe this is expected with the following note in documentation:

If there are multiple Redirect URL values configured, but no redirect_uri parameter is sent, the OAuth flow will use the first Redirect URL listed on the App Management page.

AFAICT, @slack/bolt relies on this behavior when using the default installer with ExpressReceiver. I'm also finding that when the redirectUri is provided, it appears as a query parameter of the installation URL.

It works as expected if I uncomment the 2 lines in my example.

For clarification, does this refer to the redirect_uri not appearing, or the installation not working overall?

Adding the following line to callbackOptions was an additional step needed of the installer options to complete my OAuth flow, and I'm curious if this fixes things for you:

      success: (installation, installUrlOptions, req, res) => {
        console.log('success installation', installation)
+       res.end("The installation succeeded!");
      },

If the above isn't working, I'm wondering if the variables you're passing to ExpressReceiver match credentials on app settings, as well as the version of @slack/bolt you're using?

On setup, the installer should be handling redirects to these routes, but please let me know if something seems off! 👾

@jfbn
Copy link
Author

jfbn commented Mar 11, 2025

Hi @zimeg, thank you for your reply.

I have resolved my issues with the redirect URI. Turns out that because I didn't provide an explicit redirectUri it was inferred from the first listed URL on the App Management Page, as you proposed.

Adding the following line to callbackOptions was an additional step needed of the installer options to complete my OAuth flow, and I'm curious if this fixes things for you:

When configuring the callbackOptions on a ExpressReceiver it looks like the res object does not have a send method available. The example under installer options that you sent assumes the regular HTTP receiver I suspect.

I realize this is unrelated to the issue I opened, but I'm still curious about it.

Lastly, where do you propose I ask questions about configuring the bolt sdk in the future?

I am trying to understand how I can persist state through the OAuth flow and into my storeInstallation handler (I need to persist data that came from the the context of the application where the app installation was initiated, with the installation in our database).

@zimeg
Copy link
Member

zimeg commented Mar 12, 2025

@jfbn I'm glad to know the missing redirectUri pointed towards the fallback behavior happening!

When configuring the callbackOptions on a ExpressReceiver it looks like the res object does not have a send method available. The example under installer options that you sent assumes the regular HTTP receiver I suspect.

Great callout! I'll update that example - I shouldn't have added an "s" to "end" 😉

I am trying to understand how I can persist state through the OAuth flow and into my storeInstallation handler

Depending on what's being stored, I'm wondering if the beforeInstallation custom callback might be useful for saving state details to a database before the success callback? Let me know if this seems promising!

Lastly, where do you propose I ask questions about configuring the bolt sdk in the future?

Please feel welcomed writing in here 🙏 ✨ Issues are a great place for clarifying all things Bolt, SDKs, tooling, docs, and the like! It helps us organize info and IMO issues can be a nice freeform reference with examples 📚

@zimeg zimeg removed the needs info An issue that is claimed to be a bug and hasn't been reproduced, or otherwise needs more info label Mar 12, 2025
@jfbn
Copy link
Author

jfbn commented Mar 12, 2025

Thank you again for taking your time helping me out @zimeg, it's dearly appreciated.

I am going to hijack this entire thread now for asking some more questions. I suspect that I am fundamentally misunderstanding something.

I will try to chalk up our use case.

We are a SaaS. We have users that are in different "groups" on our platform. Those groups typically (almost always) relate to one of our customers, who themselves have their own Slack workspace.

We want to, based on our services, send Slack messages to their workspace from time to time.

We want to have a Add to Slack button somewhere on our platform, that will install our Slack app in their workspace. When that happens, we want to persist the relation of that workspace ID together with that user (and the users ID as it is on our platform) and the unique "group identifier" which is data that exists in our platform.

Therefore, I see it necessary to pass along, from our platform, through the Add to Slack functionality, some meta data about which of our groups that user belongs to, so that we can make the proper database insert in the Bolt Installation Store success callback (basically here I want to make a new record in our SlackWorkspaces table to relate our internal "group" with the new Slack workspace.

After having thought about it for a bit, and now typing this out, I'm starting to feel like I'm going about this backwards.

I added the beforeInstallation callback as you proposed, and fetched the state from the request URL there -- but as I anticipated due to having tried something similar before, that state object is not the same state query param that was passed on the initial <our-slack-service>/slack/install?state=<our-custom-state>. That state is being lost in transmission somewhere.

I'm sorry if I'm confusing you here, it's likely that I misunderstand some basics of OAuth and Auth in general.

@jfbn
Copy link
Author

jfbn commented Mar 12, 2025

Update:

I'm looking at this example from the non-bolt documentation

It looks like I could go this route to persist data through the OAuth flow using cookies.

However, I still need to pass this data on further to my installationStore handler, so that I can store this meta data. I don't see how I would go about that, perhaps I need to use the metadata property on the installation object..?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question M-T: User needs support to use the project
Projects
None yet
Development

No branches or pull requests

2 participants