MCPcopy Create free account
hub / github.com/bytebase/bytebase / UserInfo

Method UserInfo

backend/plugin/idp/oauth2/oauth2.go:90–151  ·  view source on GitHub ↗

UserInfo returns the parsed user information using the given OAuth2 token.

(token string)

Source from the content-addressed store, hash-verified

88
89// UserInfo returns the parsed user information using the given OAuth2 token.
90func (p *IdentityProvider) UserInfo(token string) (*storepb.IdentityProviderUserInfo, map[string]any, error) {
91 req, err := http.NewRequest(http.MethodGet, p.config.UserInfoUrl, nil)
92 if err != nil {
93 return nil, nil, errors.Wrap(err, "failed to new http request")
94 }
95 req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token))
96 resp, err := p.client.Do(req)
97 if err != nil {
98 slog.Error("Failed to get user information", slog.String("token", token), log.BBError(err))
99 return nil, nil, errors.Wrap(err, "failed to get user information")
100 }
101 defer resp.Body.Close()
102 body, err := io.ReadAll(resp.Body)
103 if err != nil {
104 slog.Error("Failed to read response body", slog.String("token", token), log.BBError(err))
105 return nil, nil, errors.Wrap(err, "failed to read response body")
106 }
107
108 if resp.StatusCode != http.StatusOK {
109 slog.Error("Unexpected status code from user info endpoint", slog.Int("status", resp.StatusCode), slog.String("body", string(body)))
110 return nil, nil, errors.Errorf("user info request failed with status %d", resp.StatusCode)
111 }
112
113 var claims map[string]any
114 if err := json.Unmarshal(body, &claims); err != nil {
115 slog.Error("Failed to unmarshal response body", slog.String("token", token), slog.String("body", string(body)), log.BBError(err))
116 return nil, nil, errors.Wrap(err, "failed to unmarshal response body")
117 }
118 slog.Debug("User info", slog.Any("claims", claims))
119
120 userInfo := &storepb.IdentityProviderUserInfo{}
121 if v, ok := idp.GetValueWithKey(claims, p.config.FieldMapping.Identifier).(string); ok {
122 userInfo.Identifier = v
123 }
124
125 // GitHub-specific: when the identifier field (typically "email") is missing because the
126 // user's email is private, fetch it from the /user/emails endpoint.
127 if userInfo.Identifier == "" && p.config.FieldMapping.Identifier == "email" && isGitHubUserInfoURL(p.config.UserInfoUrl) {
128 if email, err := p.fetchGitHubPrimaryEmail(token); err == nil && email != "" {
129 userInfo.Identifier = email
130 claims["email"] = email
131 }
132 }
133
134 if p.config.FieldMapping.DisplayName != "" {
135 if v, ok := idp.GetValueWithKey(claims, p.config.FieldMapping.DisplayName).(string); ok {
136 userInfo.DisplayName = v
137 }
138 }
139 if userInfo.DisplayName == "" {
140 userInfo.DisplayName = userInfo.Identifier
141 }
142 if p.config.FieldMapping.Phone != "" {
143 if v, ok := idp.GetValueWithKey(claims, p.config.FieldMapping.Phone).(string); ok {
144 // Only set phone if it's valid.
145 if err := common.ValidatePhone(v); err == nil {
146 userInfo.Phone = v
147 }

Calls 14

BBErrorFunction · 0.92
GetValueWithKeyFunction · 0.92
ValidatePhoneFunction · 0.92
isGitHubUserInfoURLFunction · 0.85
DoMethod · 0.80
ErrorfMethod · 0.80
UnmarshalMethod · 0.80
DebugMethod · 0.80
StringMethod · 0.65
CloseMethod · 0.65
SetMethod · 0.45

Tested by 3

TestIdentityProviderFunction · 0.76