feat: auth handlers
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"backend/internal/api/dto"
|
||||
"backend/internal/domain"
|
||||
"backend/internal/usecase"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
authService usecase.AuthService
|
||||
}
|
||||
|
||||
func NewAuthHandler(authService *usecase.AuthService) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
authService: *authService,
|
||||
}
|
||||
}
|
||||
|
||||
func (h *AuthHandler) GenerateChallenge(c *fiber.Ctx) error {
|
||||
var req dto.ChallengeRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "invalid request body",
|
||||
})
|
||||
}
|
||||
challenge, err := h.authService.GenerateChallenge(c.Context(), req.PubKey)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "failed to generate challenge",
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusOK).JSON(
|
||||
dto.ChallengeResponse{
|
||||
Message: challenge.Message.String(),
|
||||
TimeStamp: challenge.TimeStamp.String(),
|
||||
ExpiresAt: challenge.ExpiresAt.String(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Authenticate(c *fiber.Ctx) error {
|
||||
var req dto.AuthenticateRequest
|
||||
if err := c.BodyParser(&req); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "invalid request body",
|
||||
})
|
||||
}
|
||||
|
||||
messageUUID, err := uuid.Parse(req.Message)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "invalid message format",
|
||||
})
|
||||
}
|
||||
|
||||
challenge := &domain.Challenge{
|
||||
Message: messageUUID,
|
||||
TimeStamp: time.Now().UTC(),
|
||||
ExpiresAt: time.Now().Add(5 * time.Minute),
|
||||
}
|
||||
|
||||
clientIP := c.IP()
|
||||
userAgent := c.Get("User-Agent")
|
||||
|
||||
userToken, err := h.authService.Authenticate(
|
||||
c.Context(),
|
||||
req.PubKey,
|
||||
req.Signature,
|
||||
challenge,
|
||||
// add chainID to cfg
|
||||
1,
|
||||
clientIP,
|
||||
userAgent,
|
||||
)
|
||||
if err != nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).JSON(dto.AuthenticateResponse{
|
||||
AuthorizationToken: userToken.AuthorizationToken,
|
||||
RefreshToken: userToken.RefreshToken,
|
||||
ExpiresAt: userToken.ExpiresAt,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"backend/pkg/jwt"
|
||||
"strings"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
const userClaimsKey = "User-Claims"
|
||||
|
||||
func JWTAuthMiddleware(secret []byte) fiber.Handler {
|
||||
return func(c *fiber.Ctx) error {
|
||||
authHeader := c.Get("Authorization")
|
||||
if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"error": "missing or invalid Authorization header",
|
||||
})
|
||||
}
|
||||
|
||||
tokenString := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
claims, err := jwt.ParseToken(tokenString, secret)
|
||||
if err != nil || claims == nil {
|
||||
return c.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||
"error": "invalid or expired token",
|
||||
})
|
||||
}
|
||||
|
||||
c.Locals(userClaimsKey, claims)
|
||||
return c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func GetUserClaims(c *fiber.Ctx) *jwt.UserClaims {
|
||||
claims, _ := c.Locals(userClaimsKey).(*jwt.UserClaims)
|
||||
return claims
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"backend/config"
|
||||
"backend/internal/app"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
func Run(cfg config.Server, app *app.AppContainer) {
|
||||
fiberApp := fiber.New()
|
||||
api := fiberApp.Group("/api")
|
||||
// register routes here
|
||||
registerPublicRoutes(api, app)
|
||||
|
||||
log.Fatal(fiberApp.Listen(fmt.Sprintf("%s:%d", cfg.Host, cfg.Port)))
|
||||
}
|
||||
|
||||
func registerPublicRoutes(router fiber.Router, app *app.AppContainer) {
|
||||
authgroup := router.Group("/auth")
|
||||
|
||||
//TODO: implement handlers
|
||||
authgroup.Post("/challenge")
|
||||
authgroup.Post("/authenticate")
|
||||
}
|
||||
Reference in New Issue
Block a user