Identity links allows users to share their Slack information with you when they click a link from your service. When a user clicks your your link, we utilize OpenID Connect (OIDC) standard to send you their information.
In addition, you may want to catch up on this documentation first before continuing on:
In order to receive a user’s information when a link is clicked, you'll first need to verify that you own your domain(s).
Please reach out to partner engineering with a list of domains you'd like to verify for your test apps.
The next step is to implement SIWS for your service using OpenID Connect. This is not publicly available, so you’ll need to complete the following steps.
Choose an existing OpenID Connect Relying Party client for your tech stack (or create your own by following the standard) and point it toward Slack’s OpenID configuration URL. In this example we are using Auth0 as our client, but feel free to use whatever you’d like.
Navigate to your app's Oauth and Permissions and add a redirect URL where you want the OpenID flow to redirect after it’s completed. Click Save. For an Auth0 service, it may look like the following:
https://slacktest.us.auth0.com/login/callback
You'll need to add user token scopes to enable SIWS. Add the following:
identity.basic
identity.email
identity.team
identity.avatar
Note your Client ID and Client Secret from the Basic Information page.
Navigate to your OpenID connect Relying Party client (Auth0), Enterprise, then Connections. Select OpenID Connect to create a new connection.
For Logo URL, feel free to use this sample URL:
https://a.slack-edge.com/80588/marketing/img/meta/favicon-32.png
For Issuer URL, use this URL (the key parameter will be required until this feature is publicly released):
https://slack.com/.well-known/openid-configuration?key=zQqzXfb677bpMKw0idKC5WkVLyqk04PWMsWYJDKqMUUuu
We support both Front Channel and Back Channel types.
If you use Back Channel, you’ll need to enter your Client Secret as well. You’ll also need to click Issuer Details and check whether or not the Token Endpoint is filled in. If it is not filled in, please enter https://slack.com/api/openid.connect.token
.
We noticed that using the Front Channel method means that cookies are not sent by default in Chrome once the form_post
actually posts due to the SameSite restriction. If this means nothing to you, feel free to ignore!
(This endpoint is subject to change - we will alert you if we change it)
Under Scopes, leave openid profile email
, but add the identity scopes from your Slack App Scopes. It should look like the following when you’re done:
openid profile email identity.basic identity.email identity.team identity.avatar
Save your changes.
For reference, here is a fully completed Auth0 configuration page:
From the OpenID Connect page, select Try and this should now work!
After the domain has been configured, verified, and enabled, Slack will prompt the user if they would like to additionally transfer their Slack identity to you after a link (e.g. https://your-service.net/work-object/1
) that conforms to the domain pattern is clicked in Slack. Subsequent links clicked will not trigger this prompt.
If a user clicks Accept, Slack will redirect the user to an endpoint with a login hint to start the identity transfer.
If the user clicks Decline, we'll redirect to the link clicked.
Slack will redirect to a login initiation endpoint that you have specified in your app's configuration with the following parameters:
name | value | notes |
---|---|---|
iss | https://slack.com | |
login_hint | JWT-encoded target user information | Atlassian may JWT decode this and check if the target user is already logged-in, bypassing the OpenID connect flow |
The OpenID Connect specification for Initiating Login from a Third Party specifies how this endpoint is used. After receiving the request, your app will start an OpenID Connect authentication similar to the SIWS flow described above, but appending the login_hint
parameter to the authorization URL.
When the flow is complete, there should be an additional key set with the claims called https://slack.com/target_uri
, which is the URI that the user originally clicked. Note that Auth0 renames this key to https://slack:com/target_uri
.
What does everything look like once setup is completed? We're glad you asked!
https://slack.com/openid/connect/authorize
) as in the following example: GET /siws/authorize?
response_type=id_token
&client_id=6371490080.1055357699042
&redirect_uri=https%3A%2F%2Fid.test.net%2Fsiws%2Fauth
&scope=openid%20email%20profile
&login_hint=T5J4Q04QG-W1H5Z2EHE-bjzess81jq7ehbvq6ewta90pllihsqor
&response_mode=form_post
&state=af0ifjsldkj
&nonce=n-0S6_WzA2Mj HTTP/1.1
Host: slack.com
login_hint
does not match an existing stored link click, the authentication request will fail.https://id.test.net/siws/auth
) with the following parameters:name | value |
---|---|
id_token | JWT-encoded payload |
expires_in | 300 |
state | af0ifjsldkj (matches state sent in authentication request) |
After decoding, the JWT-encoded payload will include the following:
{
"iss": "https://slack.com",
"sub": "imontoya@slack-corp.com",
"aud": "6371490080.1055357699042",
"exp": 1592939535,
"iat": 1592939235,
"auth_time": 1592939235,
"nonce": "n-0S6_WzA2Mj",
"email": "imontoya@slack-corp.com",
"locale": "en-US",
"name": "Inigo Montoya",
"given_name": "Inigo",
"family_name": "Montoya",
"picture": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_512.png",
"https://slack.com/user_id": "U06AXEE2U",
"https://slack.com/user_image_24": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_24.png",
"https://slack.com/user_image_32": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_32.png",
"https://slack.com/user_image_48": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_48.png",
"https://slack.com/user_image_72": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_72.png",
"https://slack.com/user_image_192": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_192.png",
"https://slack.com/user_image_512": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_512.png",
"https://slack.com/user_image_1024": "https://s3-us-west-2.amazonaws.com/slack-files-dev2/avatars/2017-11-15/19281328432_18916452ce6b631c669f_1024.png",
"https://slack.com/team_id": "T06AXEE2C",
"https://slack.com/team_name": "Inigo Test",
"https://slack.com/team_domain": "inigotest",
"https://slack.com/team_image_34": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-34.png",
"https://slack.com/team_image_44": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-44.png",
"https://slack.com/team_image_68": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-68.png",
"https://slack.com/team_image_88": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-88.png",
"https://slack.com/team_image_102": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-102.png",
"https://slack.com/team_image_132": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-132.png",
"https://slack.com/team_image_230": "https://slack.com/dev-cdn/v1587409668/img/avatars-teams/ava_0003-230.png",
"https://slack.com/team_image_default": true,
"https://slack.com/target_uri": "https://inigojiratest.test.net/browse/PLAT-1"
}
You must verify that the nonce
matches the one originally sent. It should also verify the JWT using the JWKS defined by Slack, and verify that the JWT has not expired.
You can check whether an account with this email already exists. If it does not, you can automatically provision an account for this user. If it does, it will add SIWS as an additional login method for this account.