[auth] protect registration endpoint in private mode

This commit is contained in:
Aleksandr Soloshenko 2024-03-01 23:56:17 +07:00
parent 9dcb01f170
commit 471b0c4c14
9 changed files with 80 additions and 18 deletions

View File

@ -5,6 +5,7 @@
###
POST {{baseUrl}}/api/mobile/v1/device HTTP/1.1
Authorization: 123456789
Content-Type: application/json
{

View File

@ -6,6 +6,7 @@ import (
"github.com/capcom6/go-infra-fx/config"
"github.com/capcom6/go-infra-fx/db"
"github.com/capcom6/go-infra-fx/http"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
"github.com/capcom6/sms-gateway/internal/sms-gateway/tasks"
"go.uber.org/fx"
@ -51,4 +52,10 @@ var Module = fx.Module(
Interval: time.Duration(cfg.Tasks.Hashing.IntervalSeconds) * time.Second,
}
}),
fx.Provide(func(cfg Config) auth.Config {
return auth.Config{
Mode: auth.Mode(cfg.Gateway.Mode),
PrivateToken: cfg.Gateway.PrivateToken,
}
}),
)

View File

@ -11,6 +11,7 @@ import (
"github.com/capcom6/go-infra-fx/validator"
appconfig "github.com/capcom6/sms-gateway/internal/config"
"github.com/capcom6/sms-gateway/internal/sms-gateway/handlers"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
"github.com/capcom6/sms-gateway/internal/sms-gateway/tasks"
@ -28,6 +29,7 @@ var Module = fx.Module(
validator.Module,
handlers.Module,
services.Module,
auth.Module,
repositories.Module,
db.Module,
tasks.Module,

View File

@ -5,6 +5,7 @@ import (
"fmt"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
@ -23,7 +24,7 @@ const (
type ThirdPartyHandlerParams struct {
fx.In
AuthSvc *services.AuthService
AuthSvc *auth.Service
MessagesSvc *services.MessagesService
DevicesSvc *services.DevicesService
@ -34,7 +35,7 @@ type ThirdPartyHandlerParams struct {
type thirdPartyHandler struct {
Handler
authSvc *services.AuthService
authSvc *auth.Service
messagesSvc *services.MessagesService
devicesSvc *services.DevicesService
}

View File

@ -7,6 +7,7 @@ import (
"github.com/capcom6/go-infra-fx/http/apikey"
"github.com/capcom6/sms-gateway/internal/sms-gateway/models"
"github.com/capcom6/sms-gateway/internal/sms-gateway/modules/auth"
"github.com/capcom6/sms-gateway/internal/sms-gateway/repositories"
"github.com/capcom6/sms-gateway/internal/sms-gateway/services"
"github.com/capcom6/sms-gateway/pkg/smsgateway"
@ -21,7 +22,7 @@ import (
type mobileHandler struct {
Handler
authSvc *services.AuthService
authSvc *auth.Service
messagesSvc *services.MessagesService
idGen func() string
@ -169,7 +170,14 @@ func (h *mobileHandler) authorize(handler func(models.Device, *fiber.Ctx) error)
func (h *mobileHandler) Register(router fiber.Router) {
router = router.Group("/mobile/v1")
router.Post("/device", limiter.New(), h.postDevice)
router.Post("/device", limiter.New(), func(c *fiber.Ctx) error {
token := c.Get(fiber.HeaderAuthorization)
if h.authSvc.AuthorizeRegistration(token) != nil {
return fiber.ErrUnauthorized
}
return c.Next()
}, h.postDevice)
router.Use(apikey.New(apikey.Config{
Authorizer: func(token string) bool {
@ -189,7 +197,7 @@ type MobileHandlerParams struct {
Logger *zap.Logger
Validator *validator.Validate
AuthSvc *services.AuthService
AuthSvc *auth.Service
MessagesSvc *services.MessagesService
}

View File

@ -0,0 +1,14 @@
package auth
import (
"go.uber.org/fx"
"go.uber.org/zap"
)
var Module = fx.Module(
"auth",
fx.Decorate(func(log *zap.Logger) *zap.Logger {
return log.Named("auth")
}),
fx.Provide(New),
)

View File

@ -1,4 +1,4 @@
package services
package auth
import (
"fmt"
@ -11,7 +11,9 @@ import (
"go.uber.org/zap"
)
type AuthService struct {
type Service struct {
config Config
users *repositories.UsersRepository
devices *repositories.DevicesRepository
@ -20,14 +22,14 @@ type AuthService struct {
idgen func() string
}
func (s *AuthService) RegisterUser(login, password string) (models.User, error) {
func (s *Service) RegisterUser(login, password string) (models.User, error) {
user := models.User{
ID: login,
}
var err error
if user.PasswordHash, err = crypto.MakeBCryptHash(password); err != nil {
return user, err
return user, fmt.Errorf("can't hash password: %w", err)
}
if err = s.users.Insert(&user); err != nil {
@ -37,7 +39,7 @@ func (s *AuthService) RegisterUser(login, password string) (models.User, error)
return user, nil
}
func (s *AuthService) RegisterDevice(userID string, name, pushToken *string) (models.Device, error) {
func (s *Service) RegisterDevice(userID string, name, pushToken *string) (models.Device, error) {
device := models.Device{
ID: s.idgen(),
Name: name,
@ -49,11 +51,23 @@ func (s *AuthService) RegisterDevice(userID string, name, pushToken *string) (mo
return device, s.devices.Insert(&device)
}
func (s *AuthService) UpdateDevice(id, pushToken string) error {
func (s *Service) UpdateDevice(id, pushToken string) error {
return s.devices.UpdateToken(id, pushToken)
}
func (s *AuthService) AuthorizeDevice(token string) (models.Device, error) {
func (s *Service) AuthorizeRegistration(token string) error {
if s.config.Mode == ModePublic {
return nil
}
if token == s.config.PrivateToken {
return nil
}
return fmt.Errorf("invalid token")
}
func (s *Service) AuthorizeDevice(token string) (models.Device, error) {
device, err := s.devices.GetByToken(token)
if err != nil {
return device, err
@ -66,7 +80,7 @@ func (s *AuthService) AuthorizeDevice(token string) (models.Device, error) {
return device, nil
}
func (s *AuthService) AuthorizeUser(username, password string) (models.User, error) {
func (s *Service) AuthorizeUser(username, password string) (models.User, error) {
user, err := s.users.GetByLogin(username)
if err != nil {
return user, err
@ -75,22 +89,30 @@ func (s *AuthService) AuthorizeUser(username, password string) (models.User, err
return user, crypto.CompareBCryptHash(user.PasswordHash, password)
}
type AuthServiceParams struct {
type Config struct {
Mode Mode
PrivateToken string
}
type Params struct {
fx.In
Config Config
Users *repositories.UsersRepository
Devices *repositories.DevicesRepository
Logger *zap.Logger
}
func NewAuthService(params AuthServiceParams) *AuthService {
func New(params Params) *Service {
idgen, _ := nanoid.Standard(21)
return &AuthService{
return &Service{
config: params.Config,
users: params.Users,
devices: params.Devices,
logger: params.Logger.Named("AuthService"),
logger: params.Logger.Named("Service"),
idgen: idgen,
}
}

View File

@ -0,0 +1,8 @@
package auth
type Mode string
const (
ModePublic Mode = "public"
ModePrivate Mode = "private"
)

View File

@ -11,7 +11,6 @@ var Module = fx.Module(
return log.Named("services")
}),
fx.Provide(
NewAuthService,
NewMessagesService,
NewPushService,
NewDevicesService,