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

Method ExchangeToken

backend/api/v1/auth_service.go:1377–1432  ·  view source on GitHub ↗

ExchangeToken exchanges an external OIDC token for a Bytebase access token. Used by CI/CD pipelines with Workload Identity Federation.

(ctx context.Context, req *connect.Request[v1pb.ExchangeTokenRequest])

Source from the content-addressed store, hash-verified

1375// ExchangeToken exchanges an external OIDC token for a Bytebase access token.
1376// Used by CI/CD pipelines with Workload Identity Federation.
1377func (s *AuthService) ExchangeToken(ctx context.Context, req *connect.Request[v1pb.ExchangeTokenRequest]) (*connect.Response[v1pb.ExchangeTokenResponse], error) {
1378 request := req.Msg
1379
1380 if request.Token == "" {
1381 return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("token is required"))
1382 }
1383 if request.Email == "" {
1384 return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("email is required"))
1385 }
1386
1387 if err := validateWorkloadIdentityEmail(request.Email); err != nil {
1388 return nil, connect.NewError(connect.CodeInvalidArgument,
1389 invalidAccountEmailError("workload identity", request.Email, err))
1390 }
1391
1392 // Find workload identity by email (cross-workspace lookup since this is unauthenticated).
1393 wi, err := s.store.GetWorkloadIdentityByEmail(ctx, request.Email)
1394 if err != nil {
1395 return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err, "failed to find workload identity"))
1396 }
1397 if wi == nil {
1398 return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("workload identity %q not found", request.Email))
1399 }
1400 // Announce the workspace as soon as we know it (from the WI record) so
1401 // that a deactivated-WI attempt — which compliance wants to see — still
1402 // lands in the audit log.
1403 common.SetAuditWorkspaceID(ctx, wi.Workspace)
1404 if wi.MemberDeleted {
1405 return nil, connect.NewError(connect.CodeUnauthenticated,
1406 errors.New("workload identity has been deactivated"))
1407 }
1408
1409 // Get workload identity config
1410 wicConfig := wi.Config
1411 if wicConfig == nil {
1412 return nil, connect.NewError(connect.CodeInternal,
1413 errors.New("workload identity config not found"))
1414 }
1415
1416 // Validate OIDC token
1417 if _, err = wif.ValidateToken(ctx, request.Token, wicConfig); err != nil {
1418 return nil, connect.NewError(connect.CodeUnauthenticated,
1419 errors.Wrap(err, "token validation failed"))
1420 }
1421
1422 // Generate Bytebase API token using workspace from the WI record.
1423 token, err := auth.GenerateAPIToken(wi.Email, wi.Workspace, s.secret)
1424 if err != nil {
1425 return nil, connect.NewError(connect.CodeInternal,
1426 errors.Wrap(err, "failed to generate access token"))
1427 }
1428
1429 return connect.NewResponse(&v1pb.ExchangeTokenResponse{
1430 AccessToken: token,
1431 }), nil
1432}
1433
1434func getAccountRestriction(

Callers

nothing calls this directly

Calls 7

SetAuditWorkspaceIDFunction · 0.92
ValidateTokenFunction · 0.92
GenerateAPITokenFunction · 0.92
invalidAccountEmailErrorFunction · 0.85
ErrorfMethod · 0.80

Tested by

no test coverage detected