Fix #1078 Add Sign in with Slack (OpenID Connect) support#1079
Fix #1078 Add Sign in with Slack (OpenID Connect) support#1079seratch merged 2 commits intoslackapi:mainfrom
Conversation
Codecov Report
@@ Coverage Diff @@
## main #1079 +/- ##
==========================================
- Coverage 84.15% 83.88% -0.28%
==========================================
Files 99 99
Lines 9255 9304 +49
==========================================
+ Hits 7789 7805 +16
- Misses 1466 1499 +33
Continue to review full report at Codecov.
|
seratch
left a comment
There was a problem hiding this comment.
comments for reviewers
| @@ -0,0 +1,22 @@ | |||
| _metadata: | |||
There was a problem hiding this comment.
The minimum App Manifest of an OpenID Connect app
| authorization_url_generator = OpenIDConnectAuthorizeUrlGenerator( | ||
| client_id=client_id, | ||
| scopes=scopes, | ||
| redirect_uri=redirect_uri, |
There was a problem hiding this comment.
Unlike the existing authorize URL, redirect_uri is mandatory for building OpenID Connect authorize URL.
| slack-sdk | ||
| Flask>=2,<3 | ||
| pyjwt>=2.1,<3 | ||
| cryptography>=3.4,<4 |
There was a problem hiding this comment.
In addition to pyjwt, cryptography is required for RS256 algorithm
| "response_type=code&" | ||
| f"state={state}&" | ||
| f"client_id={self.client_id}&" | ||
| f"scope={scopes}&" |
There was a problem hiding this comment.
The user scopes like oauth in the Slack app configuration page are set as "scope" (not "user_scope")
| f"scope={scopes}&" | ||
| f"redirect_uri={self.redirect_uri}" | ||
| ) | ||
| if nonce is not None: |
There was a problem hiding this comment.
nonce parameter is an optional one in the OpenID Connect 1.0 Specification https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
| self.api_methods_to_call.remove(method(users="U123,U234")["method"]) | ||
| method(users="U123,U234") | ||
| await async_method(users="U123,U234") | ||
| elif method_name == "oauth_access": |
There was a problem hiding this comment.
Just removed unused ones
filmaj
left a comment
There was a problem hiding this comment.
Nice, looks good, thanks for sharing. It seems like the pattern to implement new API methods is straightforward and clear. As someone new to the project, the integration tests / sample applications are very helpful, too!
| # Can be fetched by running `var methodNames = [].slice.call(document.getElementsByClassName('bold')).map(e => e.text);console.log(methodNames.toString());console.log(methodNames.length);` on https://api.slack.com/methods | ||
| all_api_methods = "admin.analytics.getFile,admin.apps.approve,admin.apps.clearResolution,admin.apps.restrict,admin.apps.uninstall,admin.apps.approved.list,admin.apps.requests.list,admin.apps.restricted.list,admin.auth.policy.assignEntities,admin.auth.policy.getEntities,admin.auth.policy.removeEntities,admin.barriers.create,admin.barriers.delete,admin.barriers.list,admin.barriers.update,admin.conversations.archive,admin.conversations.convertToPrivate,admin.conversations.create,admin.conversations.delete,admin.conversations.getConversationPrefs,admin.conversations.getCustomRetention,admin.conversations.getTeams,admin.conversations.invite,admin.conversations.removeCustomRetention,admin.conversations.rename,admin.conversations.search,admin.conversations.setConversationPrefs,admin.conversations.setCustomRetention,admin.conversations.setTeams,admin.conversations.unarchive,admin.conversations.ekm.listOriginalConnectedChannelInfo,admin.conversations.restrictAccess.addGroup,admin.conversations.restrictAccess.listGroups,admin.conversations.restrictAccess.removeGroup,admin.emoji.add,admin.emoji.addAlias,admin.emoji.list,admin.emoji.remove,admin.emoji.rename,admin.inviteRequests.approve,admin.inviteRequests.deny,admin.inviteRequests.list,admin.inviteRequests.approved.list,admin.inviteRequests.denied.list,admin.teams.admins.list,admin.teams.create,admin.teams.list,admin.teams.owners.list,admin.teams.settings.info,admin.teams.settings.setDefaultChannels,admin.teams.settings.setDescription,admin.teams.settings.setDiscoverability,admin.teams.settings.setIcon,admin.teams.settings.setName,admin.usergroups.addChannels,admin.usergroups.addTeams,admin.usergroups.listChannels,admin.usergroups.removeChannels,admin.users.assign,admin.users.invite,admin.users.list,admin.users.remove,admin.users.setAdmin,admin.users.setExpiration,admin.users.setOwner,admin.users.setRegular,admin.users.session.clearSettings,admin.users.session.getSettings,admin.users.session.invalidate,admin.users.session.list,admin.users.session.reset,admin.users.session.setSettings,api.test,apps.connections.open,apps.uninstall,apps.event.authorizations.list,auth.revoke,auth.test,auth.teams.list,bots.info,calls.add,calls.end,calls.info,calls.update,calls.participants.add,calls.participants.remove,chat.delete,chat.deleteScheduledMessage,chat.getPermalink,chat.meMessage,chat.postEphemeral,chat.postMessage,chat.scheduleMessage,chat.unfurl,chat.update,chat.scheduledMessages.list,conversations.archive,conversations.close,conversations.create,conversations.history,conversations.info,conversations.invite,conversations.join,conversations.kick,conversations.leave,conversations.list,conversations.mark,conversations.members,conversations.open,conversations.rename,conversations.replies,conversations.setPurpose,conversations.setTopic,conversations.unarchive,dialog.open,dnd.endDnd,dnd.endSnooze,dnd.info,dnd.setSnooze,dnd.teamInfo,emoji.list,files.delete,files.info,files.list,files.revokePublicURL,files.sharedPublicURL,files.upload,files.comments.delete,files.remote.add,files.remote.info,files.remote.list,files.remote.remove,files.remote.share,files.remote.update,migration.exchange,oauth.access,oauth.token,oauth.v2.access,pins.add,pins.list,pins.remove,reactions.add,reactions.get,reactions.list,reactions.remove,reminders.add,reminders.complete,reminders.delete,reminders.info,reminders.list,rtm.connect,rtm.start,search.all,search.files,search.messages,stars.add,stars.list,stars.remove,team.accessLogs,team.billableInfo,team.info,team.integrationLogs,team.profile.get,usergroups.create,usergroups.disable,usergroups.enable,usergroups.list,usergroups.update,usergroups.users.list,usergroups.users.update,users.conversations,users.deletePhoto,users.getPresence,users.identity,users.info,users.list,users.lookupByEmail,users.setActive,users.setPhoto,users.setPresence,users.profile.get,users.profile.set,views.open,views.publish,views.push,views.update,workflows.stepCompleted,workflows.stepFailed,workflows.updateStep,apps.permissions.info,apps.permissions.request,apps.permissions.resources.list,apps.permissions.scopes.list,apps.permissions.users.list,apps.permissions.users.request,channels.archive,channels.create,channels.history,channels.info,channels.invite,channels.join,channels.kick,channels.leave,channels.list,channels.mark,channels.rename,channels.replies,channels.setPurpose,channels.setTopic,channels.unarchive,groups.archive,groups.create,groups.createChild,groups.history,groups.info,groups.invite,groups.kick,groups.leave,groups.list,groups.mark,groups.open,groups.rename,groups.replies,groups.setPurpose,groups.setTopic,groups.unarchive,im.close,im.history,im.list,im.mark,im.open,im.replies,mpim.close,mpim.history,mpim.list,mpim.mark,mpim.open,mpim.replies".split( | ||
| # 247 endpoints as of July 29, 2021 | ||
| # Can be fetched by running `var methodNames = [].slice.call(document.getElementsByClassName('apiReferenceFilterableList__listItemLink')).map(e => e.href.replace("https://api.slack.com/methods/", ""));console.log(methodNames.toString());console.log(methodNames.length);` on https://api.slack.com/methods |
stevengill
left a comment
There was a problem hiding this comment.
Looks great as usual Kaz! Love having examples with the code changes too.
| "admin.conversations.getCustomRetention", | ||
| "admin.conversations.removeCustomRetention", | ||
| "admin.conversations.setCustomRetention", | ||
| # TODO: Slack Connect APIs |
There was a problem hiding this comment.
I believe @srajiang will look at adding these when she gets back next week
There was a problem hiding this comment.
Great! Happy to be a reviewer for it
| ) | ||
|
|
||
|
|
||
| @app.route("/slack/oauth_redirect", methods=["GET"]) |
There was a problem hiding this comment.
Interesting that you are using the same routes we use for normal oauth
There was a problem hiding this comment.
Not strong opinion here 😸 If you prefer other paths for tutorials, we can update this example for consistency
|
|
||
| @app.route("/slack/install", methods=["GET"]) | ||
| def oauth_start(): | ||
| state = state_store.issue() |
There was a problem hiding this comment.
The line generates a new unique state parameter value. The state_store (FileOAuthStateStore in this example) stores the generated value in the local file system. And then, state_store.consume(state) in the redirect URL handler checks and deletes it.
This SDK provides local files, Amazon S3, and RDB as the backends of OAuthStateStore: https://github.com/slackapi/python-slack-sdk/tree/main/slack_sdk/oauth/state_store
If you switch to other implementation, this code works with the chosen backend without any changes.
Summary
This pull request fixes #1078 by adding the following changes to this project.
Category (place an
xin each of the[ ])/docs-src(Documents, have you run./docs.sh?)/docs-src-v2(Documents, have you run./docs-v2.sh?)/tutorial(PythOnBoardingBot tutorial)tests/integration_tests(Automated tests for this library)Requirements (place an
xin each[ ])python3 -m venv .venv && source .venv/bin/activate && ./scripts/run_validation.shafter making the changes.