87 lines
2.5 KiB
Go
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
|
|
}
|