add auth client

This commit is contained in:
Pavel 2024-01-04 17:57:30 +03:00
parent ebe7702d77
commit dc28f97562
8 changed files with 109 additions and 7 deletions

5
.env

@ -1,7 +1,7 @@
# General application settings # General application settings
APP_NAME=codeword APP_NAME=codeword
HTTP_HOST="localhost" HTTP_HOST="localhost"
HTTP_PORT="8000" HTTP_PORT="8080"
# MongoDB settings # MongoDB settings
MONGO_HOST="127.0.0.1" MONGO_HOST="127.0.0.1"
@ -33,4 +33,5 @@ SMTP_API_KEY="P0YsjUB137upXrr1NiJefHmXVKW1hmBWlpev"
SMTP_SENDER="noreply@mailing.pena.digital" SMTP_SENDER="noreply@mailing.pena.digital"
# URL settings # URL settings
DEFAULT_REDIRECTION_URL = "def.url" DEFAULT_REDIRECTION_URL = "def.url"
AUTH_REFRESH_URL = "http://localhost:8000/auth/refresh"

@ -0,0 +1,68 @@
package client
import (
"codeword/internal/models"
"encoding/json"
"fmt"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
type AuthClientDeps struct {
AuthUrl string
FiberClient *fiber.Client
Logger *zap.Logger
}
type AuthClient struct {
deps AuthClientDeps
}
func NewAuthClient(deps AuthClientDeps) *AuthClient {
if deps.FiberClient == nil {
deps.FiberClient = fiber.AcquireClient()
}
return &AuthClient{
deps: deps,
}
}
func (a *AuthClient) RefreshAuthToken(userID, signature string) (*models.RefreshResponse, error) {
body := models.AuthRequestBody{
UserID: userID,
Signature: signature,
}
bodyBytes, err := json.Marshal(body)
if err != nil {
a.deps.Logger.Error("Failed to encode request body", zap.Error(err))
return nil, err
}
agent := a.deps.FiberClient.Post(a.deps.AuthUrl)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
//todo надо что-то придумать с авторизаиционными токенами
agent.Set("Authorization", "Bearer "+"123")
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err := range errs {
a.deps.Logger.Error("Error in refresh auth token request", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs)
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from the authentication service: %d", statusCode)
a.deps.Logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var tokens models.RefreshResponse
if err := json.Unmarshal(resBody, &tokens); err != nil {
a.deps.Logger.Error("failed to unmarshal auth service response", zap.Error(err))
return nil, err
}
return &tokens, nil
}

@ -27,12 +27,14 @@ func Run(ctx context.Context, cfg initialize.Config, logger *zap.Logger) error {
codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")}) codewordRepo := repository.NewCodewordRepository(repository.Deps{Rdb: rdb, Mdb: mdb.Collection("codeword")})
userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")}) userRepo := repository.NewUserRepository(repository.Deps{Rdb: nil, Mdb: mdb.Collection("users")})
recoveryEmailSender := initialize.InitializeRecoveryEmailSender(cfg, logger) recoveryEmailSender := initialize.InitializeRecoveryEmailSender(cfg, logger)
authClient := initialize.InitializeAuthClient(cfg, logger)
recoveryService := services.NewRecoveryService(services.Deps{ recoveryService := services.NewRecoveryService(services.Deps{
Logger: logger, Logger: logger,
CodewordRepository: codewordRepo, CodewordRepository: codewordRepo,
UserRepository: userRepo, UserRepository: userRepo,
Encrypt: encrypt, Encrypt: encrypt,
AuthClient: authClient,
}) })
recoveryController := controller.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL) recoveryController := controller.NewRecoveryController(logger, recoveryService, cfg.DefaultRedirectionURL)

@ -86,7 +86,7 @@ func (r *RecoveryController) HandleRecoveryLink(c *fiber.Ctx) error {
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Recovery link expired"}) return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{"error": "Recovery link expired"})
} }
tokens, err := r.service.ExchangeForTokens(record.UserID) tokens, err := r.service.ExchangeForTokens(record.UserID, record.Sign)
if err != nil { if err != nil {
r.logger.Error("Failed to exchange recovery link for tokens", zap.Error(err)) r.logger.Error("Failed to exchange recovery link for tokens", zap.Error(err))
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"}) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Internal Server Error"})

@ -21,3 +21,11 @@ func InitializeRecoveryEmailSender(cfg Config, logger *zap.Logger) *client.Recov
CodewordPort: cfg.HTTPPort, CodewordPort: cfg.HTTPPort,
}) })
} }
func InitializeAuthClient(cfg Config, logger *zap.Logger) *client.AuthClient {
return client.NewAuthClient(client.AuthClientDeps{
AuthUrl: cfg.AuthURL,
Logger: logger,
FiberClient: &fiber.Client{},
})
}

@ -30,6 +30,7 @@ type Config struct {
SmtpApiKey string `env:"SMTP_API_KEY"` SmtpApiKey string `env:"SMTP_API_KEY"`
SmtpSender string `env:"SMTP_SENDER"` SmtpSender string `env:"SMTP_SENDER"`
DefaultRedirectionURL string `env:"DEFAULT_REDIRECTION_URL"` DefaultRedirectionURL string `env:"DEFAULT_REDIRECTION_URL"`
AuthURL string `env:"AUTH_REFRESH_URL"`
} }
func LoadConfig() (*Config, error) { func LoadConfig() (*Config, error) {

11
internal/models/auth.go Normal file

@ -0,0 +1,11 @@
package models
type AuthRequestBody struct {
UserID string `json:"userId"`
Signature string `json:"signature"`
}
type RefreshResponse struct {
AccessToken string `json:"accessToken"`
RefreshToken string `json:"refreshToken"`
}

@ -1,6 +1,7 @@
package services package services
import ( import (
"codeword/internal/adapters/client"
"codeword/internal/models" "codeword/internal/models"
"codeword/internal/utils/encrypt" "codeword/internal/utils/encrypt"
"context" "context"
@ -24,6 +25,7 @@ type Deps struct {
CodewordRepository CodewordRepository CodewordRepository CodewordRepository
UserRepository UserRepository UserRepository UserRepository
Encrypt *encrypt.Encrypt Encrypt *encrypt.Encrypt
AuthClient *client.AuthClient
} }
type RecoveryService struct { type RecoveryService struct {
@ -31,6 +33,7 @@ type RecoveryService struct {
repositoryCodeword CodewordRepository repositoryCodeword CodewordRepository
repositoryUser UserRepository repositoryUser UserRepository
encrypt *encrypt.Encrypt encrypt *encrypt.Encrypt
authClient *client.AuthClient
} }
func NewRecoveryService(deps Deps) *RecoveryService { func NewRecoveryService(deps Deps) *RecoveryService {
@ -39,6 +42,7 @@ func NewRecoveryService(deps Deps) *RecoveryService {
repositoryCodeword: deps.CodewordRepository, repositoryCodeword: deps.CodewordRepository,
repositoryUser: deps.UserRepository, repositoryUser: deps.UserRepository,
encrypt: deps.Encrypt, encrypt: deps.Encrypt,
authClient: deps.AuthClient,
} }
} }
@ -117,8 +121,15 @@ func (s *RecoveryService) GetRecoveryRecord(ctx context.Context, key string) (*m
return req, nil return req, nil
} }
// ExchangeForTokens обменивает ссылку восстановления на токены используя сервис аутентификации. func (s *RecoveryService) ExchangeForTokens(userID string, signature string) (map[string]string, error) {
func (s *RecoveryService) ExchangeForTokens(userID string) (map[string]string, error) { tokens, err := s.authClient.RefreshAuthToken(userID, signature)
// TODO if err != nil {
return nil, nil s.logger.Error("Failed to refresh auth token", zap.Error(err))
return nil, err
}
return map[string]string{
"accessToken": tokens.AccessToken,
"refreshToken": tokens.RefreshToken,
}, nil
} }