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

Method getOrCreateUserWithIDP

backend/api/v1/auth_service.go:557–775  ·  view source on GitHub ↗

getOrCreateUserWithIDP authenticates a user via an identity provider (SSO). Login API has allow_without_credential, so there's no workspace in the token context. We resolve workspace from the IDP entity (IDP resource_id is globally unique).

(ctx context.Context, request *v1pb.LoginRequest)

Source from the content-addressed store, hash-verified

555// Login API has allow_without_credential, so there's no workspace in the token context.
556// We resolve workspace from the IDP entity (IDP resource_id is globally unique).
557func (s *AuthService) getOrCreateUserWithIDP(ctx context.Context, request *v1pb.LoginRequest) (*store.UserMessage, error) {
558 idpID, err := common.GetIdentityProviderID(request.IdpName)
559 if err != nil {
560 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Wrapf(err, "failed to get identity provider ID"))
561 }
562 // Look up IDP without workspace filter — IDP resource_id is globally unique.
563 // The workspace is resolved from the IDP entity.
564 idp, err := s.store.GetIdentityProviderByID(ctx, idpID)
565 if err != nil {
566 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get identity provider"))
567 }
568 if idp == nil {
569 return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("identity provider not found"))
570 }
571
572 // For workspace-scoped IDPs, use the IDP's workspace.
573 // For global IDPs (SaaS), workspace is resolved after authentication from user membership.
574 workspaceID := idp.Workspace
575 externalURL, err := utils.GetEffectiveExternalURL(ctx, s.store, s.profile, workspaceID)
576 if err != nil {
577 return nil, err
578 }
579
580 var userInfo *storepb.IdentityProviderUserInfo
581 switch idp.Type {
582 case storepb.IdentityProviderType_OAUTH2:
583 oauth2Context := request.IdpContext.GetOauth2Context()
584 if oauth2Context == nil {
585 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("missing OAuth2 context"))
586 }
587 oauth2IdentityProvider, err := oauth2.NewIdentityProvider(idp.Config.GetOauth2Config())
588 if err != nil {
589 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to create new OAuth2 identity provider"))
590 }
591 redirectURL := fmt.Sprintf("%s/oauth/callback", externalURL)
592 token, err := oauth2IdentityProvider.ExchangeToken(ctx, redirectURL, oauth2Context.Code)
593 if err != nil {
594 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to exchange token"))
595 }
596 userInfo, _, err = oauth2IdentityProvider.UserInfo(token)
597 if err != nil {
598 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get user info"))
599 }
600 case storepb.IdentityProviderType_OIDC:
601 oidcContext := request.IdpContext.GetOidcContext()
602 if oidcContext == nil {
603 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("missing OIDC context"))
604 }
605
606 oidcIDP, err := oidc.NewIdentityProvider(ctx, idp.Config.GetOidcConfig())
607 if err != nil {
608 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to create new OIDC identity provider"))
609 }
610
611 redirectURL := fmt.Sprintf("%s/oidc/callback", externalURL)
612 token, err := oidcIDP.ExchangeToken(ctx, redirectURL, oidcContext.Code)
613 if err != nil {
614 return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to exchange token"))

Callers 1

authenticateLoginMethod · 0.95

Calls 15

ExchangeTokenMethod · 0.95
UserInfoMethod · 0.95
AuthenticateMethod · 0.95
syncUserGroupsMethod · 0.95
GetIdentityProviderIDFunction · 0.92
GetEffectiveExternalURLFunction · 0.92
NewIdentityProviderFunction · 0.92
NewIdentityProviderFunction · 0.92
NewIdentityProviderFunction · 0.92
ValidateEmailFunction · 0.92

Tested by

no test coverage detected