MCPcopy Index your code
hub / github.com/bytebase/bytebase / authenticate

Method authenticate

backend/api/auth/auth.go:167–230  ·  view source on GitHub ↗

authenticate is the shared authentication logic that validates JWT tokens. Returns the user and claims, or an error. This is the single source of truth for token validation.

(ctx context.Context, accessTokenStr string)

Source from the content-addressed store, hash-verified

165// authenticate is the shared authentication logic that validates JWT tokens.
166// Returns the user and claims, or an error. This is the single source of truth for token validation.
167func (in *APIAuthInterceptor) authenticate(ctx context.Context, accessTokenStr string) (*store.UserMessage, *claimsMessage, error) {
168 if accessTokenStr == "" {
169 return nil, nil, errs.New("access token not found")
170 }
171
172 claims := &claimsMessage{}
173 if _, err := jwt.ParseWithClaims(accessTokenStr, claims, func(t *jwt.Token) (any, error) {
174 if t.Method.Alg() != jwt.SigningMethodHS256.Name {
175 return nil, errs.Errorf("unexpected access token signing method=%v, expect %v", t.Header["alg"], jwt.SigningMethodHS256)
176 }
177 if kid, ok := t.Header["kid"].(string); ok {
178 if kid == "v1" {
179 return []byte(in.secret), nil
180 }
181 }
182 return nil, errs.Errorf("unexpected access token kid=%v", t.Header["kid"])
183 }); err != nil {
184 if errors.Is(err, jwt.ErrTokenExpired) {
185 return nil, nil, errs.New("access token expired")
186 }
187 return nil, nil, errs.New("failed to parse claim")
188 }
189
190 // Accept both user access tokens (bb.user.access) and OAuth2 access tokens (bb.oauth2.access)
191 if !audienceContains(claims.Audience, AccessTokenAudience) && !audienceContains(claims.Audience, OAuth2AccessTokenAudience) {
192 return nil, nil, errs.Errorf(
193 "invalid access token, audience mismatch, got %q, expected %q or %q",
194 claims.Audience,
195 AccessTokenAudience,
196 OAuth2AccessTokenAudience,
197 )
198 }
199
200 account, err := in.store.GetAccountByEmail(ctx, claims.Subject)
201 if err != nil {
202 return nil, nil, errs.Errorf("failed to find principal %q in the access token", claims.Subject)
203 }
204 if account == nil {
205 return nil, nil, errs.Errorf("principal %q not exists in the access token", claims.Subject)
206 }
207 if account.MemberDeleted {
208 return nil, nil, errs.Errorf("principal %q has been deactivated by administrators", account.Email)
209 }
210
211 // Verify workspace membership.
212 // We always require workspace_id in the claims even for non-SaaS (single workspace) mode
213 if claims.WorkspaceID == "" {
214 return nil, nil, errs.New("empty workspace in the token")
215 }
216 if err := in.verifyWorkspaceMembership(ctx, claims.WorkspaceID, account); err != nil {
217 return nil, nil, err
218 }
219
220 // Convert to UserMessage for context storage.
221 user, err := in.store.ResolvePrincipalAsUser(ctx, account)
222 if err != nil {
223 return nil, nil, err
224 }

Callers 3

WrapStreamingHandlerMethod · 0.95
authenticateConnectMethod · 0.95
AuthenticateTokenMethod · 0.95

Calls 5

ErrorfMethod · 0.80
GetAccountByEmailMethod · 0.80
audienceContainsFunction · 0.70

Tested by

no test coverage detected