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

MultiTeamsAuthorization error #1069

Open
dwiq-pfaratin opened this issue Apr 10, 2024 · 3 comments
Open

MultiTeamsAuthorization error #1069

dwiq-pfaratin opened this issue Apr 10, 2024 · 3 comments
Labels
auto-triage-stale question Further information is requested

Comments

@dwiq-pfaratin
Copy link

(Describe your issue and goal here)

Trying to install a slack bolt python app on google cloud run. This is the workflow of the app

1- user issues a /command
2- a modal is presented to capture parameters of the command
3- the bot writes the user query (as the user) and then creates a thread (so that all responses to the user /command is maintained in one thread)

The app that works end to end but the problem is the user is not notified if someone responds in the thread. This is because the thread is created by the bot in step 3 and it owns it. I have followed the steps by filmaj to no avail.

"Now, when a user goes to install the app to their workspace, your app will be able to get information about which user authorized your app and to what workspace, and you will have the ability to store the tokens associated with each user securely in whatever place you wish (a database, on the filesystem, etc.). You can now use the appropriate user token to have your app do actions completely on behalf of your user (as long as the appropriate user scopes were defined in your app)."

So step 3 should now be owned by the user not by the bot (hence get their notifications). I have implemented the oauth code as stated (here)[https://slack.dev/bolt-python/concepts#authenticating-oauth] as

oauth_settings = OAuthSettings(
    client_id = SLACK_CLIENT_ID,
    client_secret = SLACK_CLIENT_SECRET,
    scopes = bot_scopes,
    user_scopes = user_scopes,
    installation_store = FileInstallationStore(base_dir = "./data/installations"),
    state_store = FileOAuthStateStore(expiration_seconds = 600, base_dir = "./data/states"),
    callback_options = CallbackOptions(success = success, failure = failure),
    )

app = App(
    client = WebClient(token = slack_token),
    oauth_settings = oauth_settings,
    signing_secret = ss,
    raise_error_for_unhandled_request = True,
    process_before_response = True
    )

with following scopes

bot_scopes = ['app_mentions:read',
              'channels:history',
              'chat:write',
              'chat:write.customize',
              'commands',
              'groups:history',
              'groups:read',
              'groups:write.invites',
              'links:read',
              'links:write',
              'reactions:read',
              'users:read',
              'incoming-webhook']

user_scopes = ['groups:history', 'chat:write', 'reactions:read']

I manage to install the app (as a end user) on my workspace but when I click anywhere in slack my app icon under "App" section of sidebar disappears. If I try the /command I get

We apologize, but for some unknown reason, your installation with this app is no longer available. Please reinstall this app into your workspace

with this error on the backend

ERROR:slack_bolt.MultiTeamsAuthorization:Although the app should be installed into this workspace, the AuthorizeResult (returned value from authorize) for it was not found.

Reproducible in:

pip freeze | grep slack
python --version
sw_vers && uname -v # or `ver`

The slack_bolt version

1.18.1

Python runtime version

3.10.9

OS info

linux

Steps to reproduce:

see above

Expected result:

expect /command to work

Actual result:

We apologize, but for some unknown reason, your installation with this app is no longer available. Please reinstall this app into your workspace

and

ERROR:slack_bolt.MultiTeamsAuthorization:Although the app should be installed into this workspace, the AuthorizeResult (returned value from authorize) for it was not found.

Requirements

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

@filmaj filmaj added the question Further information is requested label Apr 10, 2024
@filmaj
Copy link
Contributor

filmaj commented Apr 10, 2024

If I understand the situation, you are using Google Cloud Run to host your app. GCR is a serverless system, meaning, it runs on containers that are ephemeral and disappear after each Slack event is processed by your app.

However, to store app installation information, you are using the FileInstallationStore:

FileInstallationStore(base_dir = "./data/installations"),

So, Bolt assumes that every time it runs, there will be a file in the ./data/installation directory that contains all of your applications' installation data. This will not work in a serverless environment, as the file system in each serverless invocation is clean and isolated and stateless between invocations. Nothing stored on the file system in GCR will be available the next time your GCR function is invoked.

The File Installation Store we provide as an example in Bolt is not recommended for production. For your situation, it is much better to store implement your own Installation Store that is compatible with serverless. For example, you could use a separate database that your GCR functions could interact with (store and retrieve installation information) on each invocation.

@dwiq-pfaratin
Copy link
Author

Hi

Thank you for pointing out the obvious error in my approach. Ofcourse, duh. I found and implemented this datastore pattern but am still getting failed with the error "dispatch_failed" when I run my /command <TEXT>

My setup is:

oauth_settings = OAuthSettings(
    client_id = os.environ["SLACK_CLIENT_ID"],
    client_secret = os.environ["SLACK_CLIENT_SECRET"],
    scopes = bot_scopes,
    user_scopes = user_scopes,
    install_path = "/slack/install",
    redirect_uri_path = "/slack/oauth_redirect",
    installation_store = installation_store,
    state_store = GoogleDatastoreOAuthStateStore(
        datastore_client = datastore_client,
        logger = logging.getLogger(__name__),
        ),
    callback_options = CallbackOptions(success = success, failure = failure),
    )

app = App(
    client = WebClient(token = slack_token),
    oauth_settings = oauth_settings,
    signing_secret = ss,
    raise_error_for_unhandled_request = True,
    process_before_response = True
    )
    
flask_app = Flask(__name__)
handler = SlackRequestHandler(app)

@flask_app.route("/slack/events", methods = ["POST"])
def events():
    logging.info(f'/slack/events: {request.get_json(silent = True)}')
    return handler.handle(request)

I see the following in the logs INFO:root:/slack/events: None

Copy link

👋 It looks like this issue has been open for 30 days with no activity. We'll mark this as stale for now, and wait 10 days for an update or for further comment before closing this issue out. If you think this issue needs to be prioritized, please comment to get the thread going again! Maintainers also review issues marked as stale on a regular basis and comment or adjust status if the issue needs to be reprioritized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-triage-stale question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants