package auth import ( "base/pkg/jwt" "context" "fmt" "time" "github.com/google/uuid" "base/internal/domain/auth" "base/internal/dto" ) func (s *service) GetOAuthRedirectURL(ctx context.Context, request dto.OAuthRedirectURLRequest) (string, error) { provider := s.oauthService.Client(request.Provider) state := uuid.New().String() redirectURL := provider.GetConsentAuthUrl(ctx, state) return redirectURL, nil } func (s *service) OAuthCallback(ctx context.Context, request dto.OAuthCallbackRequest) (*dto.OAuthCallbackResponse, error) { oauthProvider := s.oauthService.Client(request.Provider) token, err := oauthProvider.ExchangeCodeWithToken(ctx, request.Code) if err != nil { return nil, fmt.Errorf("failed to exchange code for token: %w", err) } userInfo, err := oauthProvider.GetUserInfo(ctx, token.AccessToken, token.RefreshToken) if err != nil { return nil, fmt.Errorf("failed to get user info: %w", err) } now := time.Now() accessExpiry := now.Add(time.Duration(token.ExpiresIn) * time.Second) refreshExpiry := now.Add(7 * 24 * time.Hour) user := &auth.User{ ID: uuid.New(), // Will be set by repository if user exists Email: userInfo.Email(), FirstName: userInfo.FirstName(), LastName: userInfo.LastName(), Status: auth.UserStatusActive, EmailVerified: true, // OAuth providers verify email CreatedAt: now, UpdatedAt: now, } account := &auth.Account{ ID: uuid.New(), Provider: request.Provider, AccessToken: &token.AccessToken, RefreshToken: &token.RefreshToken, AccessTokenExpiry: &accessExpiry, RefreshTokenExpiry: &refreshExpiry, CreatedAt: now, UpdatedAt: now, } isNewUser, err := s.userRepo.UpsertWithAccount(ctx, userInfo.Email(), user, account) if err != nil { s.logger.Error().Err(err).Msg("failed to upsert user and account") return nil, fmt.Errorf("failed to upsert user and account: %w", err) } tokens, genErr := s.jwtService.GenerateAccessRefreshTokenPair(ctx, &jwt.TokenData{Sub: user.ID.String()}) if genErr != nil { return nil, fmt.Errorf("failed to generate tokens: %w", genErr) } s.logger.Info(). Str("user_id", user.ID.String()). Str("email", user.Email). Bool("is_new_user", isNewUser). Str("provider", request.Provider.String()). Msg("OAuth callback completed successfully") return &dto.OAuthCallbackResponse{ AccessToken: tokens.AccessToken, RefreshToken: tokens.RefreshToken, IsNewUser: isNewUser, }, nil }