Skip to content

Commit bfd53c6

Browse files
committed
feat(oauth): add GetOpenIDConnectUserInfo
Closes #967.
1 parent ca62227 commit bfd53c6

3 files changed

Lines changed: 131 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3535
3636
### Added
3737

38+
- **`GetOpenIDConnectUserInfo` / `GetOpenIDConnectUserInfoContext`** — Returns identity
39+
information about the user associated with the token via `openid.connect.userInfo`.
40+
Complements the existing `GetOpenIDConnectToken` method. ([#967])
3841
- **HTTP response headers** — Slack API response headers (e.g. `X-OAuth-Scopes`,
3942
`X-Accepted-OAuth-Scopes`, `X-Ratelimit-*`) are now accessible. `AuthTestResponse`
4043
exposes a `Header` field directly. For all other methods, use

oauth.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,74 @@ func RefreshOAuthV2TokenContext(ctx context.Context, client httpClient, clientID
177177
return response, response.Err()
178178
}
179179

180+
// OpenIDConnectUserInfoResponse contains the response from openid.connect.userInfo.
181+
//
182+
// Some of the fields in the response to this method are preceded with https://slack.com/.
183+
// These fields are Slack-specific, and they're from the perspective of Slack.
184+
type OpenIDConnectUserInfoResponse struct {
185+
Ok bool `json:"ok"`
186+
187+
Sub string `json:"sub"`
188+
189+
UserID string `json:"https://slack.com/user_id"`
190+
TeamID string `json:"https://slack.com/team_id"`
191+
192+
Email string `json:"email"`
193+
EmailVerified bool `json:"email_verified"`
194+
DateEmailVerified int64 `json:"date_email_verified"`
195+
196+
Name string `json:"name"`
197+
Picture string `json:"picture"`
198+
GivenName string `json:"given_name"`
199+
FamilyName string `json:"family_name"`
200+
Locale string `json:"locale"`
201+
202+
TeamName string `json:"https://slack.com/team_name"`
203+
TeamDomain string `json:"https://slack.com/team_domain"`
204+
TeamImage34 string `json:"https://slack.com/team_image_34"`
205+
TeamImage44 string `json:"https://slack.com/team_image_44"`
206+
TeamImage68 string `json:"https://slack.com/team_image_68"`
207+
TeamImage88 string `json:"https://slack.com/team_image_88"`
208+
TeamImage102 string `json:"https://slack.com/team_image_102"`
209+
TeamImage132 string `json:"https://slack.com/team_image_132"`
210+
TeamImage230 string `json:"https://slack.com/team_image_230"`
211+
212+
// `TeamImageDefault` indicates whether the image is a default one (true), or someone
213+
// uploaded their own (false).
214+
TeamImageDefault bool `json:"https://slack.com/team_image_default"`
215+
216+
UserImage24 string `json:"https://slack.com/user_image_24"`
217+
UserImage32 string `json:"https://slack.com/user_image_32"`
218+
UserImage48 string `json:"https://slack.com/user_image_48"`
219+
UserImage72 string `json:"https://slack.com/user_image_72"`
220+
UserImage192 string `json:"https://slack.com/user_image_192"`
221+
UserImage512 string `json:"https://slack.com/user_image_512"`
222+
UserImage1024 string `json:"https://slack.com/user_image_1024"`
223+
UserImageOriginal string `json:"https://slack.com/user_image_original"`
224+
225+
SlackResponse
226+
}
227+
228+
// GetOpenIDConnectUserInfo returns the user info for the token.
229+
// For more details, see GetOpenIDConnectUserInfoContext documentation.
230+
func (api *Client) GetOpenIDConnectUserInfo() (*OpenIDConnectUserInfoResponse, error) {
231+
return api.GetOpenIDConnectUserInfoContext(context.Background())
232+
}
233+
234+
// GetOpenIDConnectUserInfoContext returns identity information about the user associated with the token.
235+
// Slack API docs: https://docs.slack.dev/reference/methods/openid.connect.userInfo
236+
func (api *Client) GetOpenIDConnectUserInfoContext(ctx context.Context) (*OpenIDConnectUserInfoResponse, error) {
237+
values := url.Values{
238+
"token": {api.token},
239+
}
240+
response := &OpenIDConnectUserInfoResponse{}
241+
err := api.postMethod(ctx, "openid.connect.userInfo", values, response)
242+
if err != nil {
243+
return nil, err
244+
}
245+
return response, response.Err()
246+
}
247+
180248
// GetOpenIDConnectToken exchanges a temporary OAuth verifier code for an access token for Sign in with Slack.
181249
// For more details, see GetOpenIDConnectTokenContext documentation.
182250
func GetOpenIDConnectToken(client httpClient, clientID, clientSecret, code, redirectURI string) (resp *OpenIDConnectResponse, err error) {

oauth_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package slack
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func getOpenIDConnectUserInfo(rw http.ResponseWriter, r *http.Request) {
12+
rw.Header().Set("Content-Type", "application/json")
13+
rw.Write([]byte(`{
14+
"ok": true,
15+
"sub": "U0R7JM",
16+
"https://slack.com/user_id": "U0R7JM",
17+
"https://slack.com/team_id": "T0R7GR",
18+
"email": "krane@slack-corp.com",
19+
"email_verified": true,
20+
"date_email_verified": 1622128723,
21+
"name": "krane",
22+
"picture": "https://secure.gravatar.com/....png",
23+
"given_name": "Bront",
24+
"family_name": "Kansen",
25+
"locale": "en-US",
26+
"https://slack.com/team_name": "Slack Corp",
27+
"https://slack.com/team_domain": "slackcorp",
28+
"https://slack.com/user_image_24": "...",
29+
"https://slack.com/user_image_32": "...",
30+
"https://slack.com/user_image_48": "...",
31+
"https://slack.com/user_image_72": "...",
32+
"https://slack.com/user_image_192": "...",
33+
"https://slack.com/user_image_512": "...",
34+
"https://slack.com/team_image_default": true
35+
}`))
36+
}
37+
38+
func TestGetOpenIDConnectUserInfo(t *testing.T) {
39+
http.HandleFunc("/openid.connect.userInfo", getOpenIDConnectUserInfo)
40+
41+
once.Do(startServer)
42+
api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
43+
44+
resp, err := api.GetOpenIDConnectUserInfo()
45+
require.NoError(t, err)
46+
47+
assert.Equal(t, "U0R7JM", resp.Sub)
48+
assert.Equal(t, "U0R7JM", resp.UserID)
49+
assert.Equal(t, "T0R7GR", resp.TeamID)
50+
assert.Equal(t, "krane@slack-corp.com", resp.Email)
51+
assert.True(t, resp.EmailVerified)
52+
assert.Equal(t, int64(1622128723), resp.DateEmailVerified)
53+
assert.Equal(t, "krane", resp.Name)
54+
assert.Equal(t, "Bront", resp.GivenName)
55+
assert.Equal(t, "Kansen", resp.FamilyName)
56+
assert.Equal(t, "en-US", resp.Locale)
57+
assert.Equal(t, "Slack Corp", resp.TeamName)
58+
assert.Equal(t, "slackcorp", resp.TeamDomain)
59+
assert.True(t, resp.TeamImageDefault)
60+
}

0 commit comments

Comments
 (0)