Token rotation must be enabled.
If the refresh token is about to expire (the SDK does this when there are less than 2 hours left on the expiry), and we run multiple functions simultaneously - in a Promise.all for instance - it seems the same refresh token is exchanged for 2 different fresh refresh tokens that have the same expires_at. At this point the SDK saves both tokens (via storeInstallation), but one is invalid and it is impossible to determine which one without trying it.
We've been having this issue since we started using the SDK.
I've tried to use the various callbacks to implement a user-land lock, but I couldn't quite get it to work because there's not enough control over what's being passed around.
Packages:
Select all that apply:
Reproducible in:
The Slack SDK version
I've tried the same with older versions and latest
"slack/bolt": "^3.22.0",
"slack/oauth": "^2.6.3",
"slack/web-api": "^6.13.0",
"slack/webhook": "^7.0.3",
"slack/bolt": "^4.6.0",
"slack/oauth": "^3.0.4",
"slack/web-api": "^7.13.0",
"slack/webhook": "^7.0.6",
Node.js runtime version
v22.22.0
OS info
Docker - node:22.22.0-alpine3.22
Steps to reproduce:
- Token rotation must be enabled
- Refresh token about to expire
- Multiple calls to a Slack function (
chat.postMessage for instance) in a Promise.all
- Internally,
authorize() is called for all calls
fetchInstallation() is called for all calls
refreshExpiringToken() is called for all calls - 2 different refresh tokens are created
storeInstallation() is called for all calls
Expected result:
A single call to storeInstallation with a installation OR multiple calls with different expires_ats
Actual result:
Multiple calls to storeInstallation, with some installations immediately invalid
Requirements
For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇
Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.
Token rotation must be enabled.
If the refresh token is about to expire (the SDK does this when there are less than 2 hours left on the expiry), and we run multiple functions simultaneously - in a Promise.all for instance - it seems the same refresh token is exchanged for 2 different fresh refresh tokens that have the same
expires_at.At this point the SDK saves both tokens (viastoreInstallation), but one is invalid and it is impossible to determine which one without trying it.We've been having this issue since we started using the SDK.
I've tried to use the various callbacks to implement a user-land lock, but I couldn't quite get it to work because there's not enough control over what's being passed around.
Packages:
Select all that apply:
@slack/web-api@slack/rtm-api@slack/webhooks@slack/oauth@slack/socket-mode@slack/typesReproducible in:
The Slack SDK version
I've tried the same with older versions and latest
Node.js runtime version
v22.22.0OS info
Docker - node:22.22.0-alpine3.22
Steps to reproduce:
chat.postMessagefor instance) in aPromise.allauthorize()is called for all callsfetchInstallation()is called for all callsrefreshExpiringToken()is called for all calls - 2 different refresh tokens are createdstoreInstallation()is called for all callsExpected result:
A single call to
storeInstallationwith a installation OR multiple calls with differentexpires_atsActual result:
Multiple calls to
storeInstallation, with some installations immediately invalidRequirements
For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇
Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.