Files
base/internal/application/auth/oauth.go
2026-04-10 18:25:21 +03:30

87 lines
2.5 KiB
Go

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
}