diff --git a/auth/auth.go b/auth/auth.go deleted file mode 100644 index e98eb087..00000000 --- a/auth/auth.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "context" - "net/http" - - "github.com/alexedwards/argon2id" - "github.com/golang-jwt/jwt/v5" - "github.com/labstack/echo/v4" - "github.com/zoriya/kyoo/keibi/dbc" -) - -type LoginDto struct { - Login string `json:"login" validate:"required"` - Password string `json:"password" validate:"required"` -} - -type RegisterDto struct { - Username string `json:"username" validate:"required"` - Email string `json:"email" validate:"required,email"` - Password string `json:"password" validate:"required"` -} - -func (h *Handler) Register(c echo.Context) error { - var req RegisterDto - err := c.Bind(&req) - if err != nil { - return echo.NewHTTPError(http.StatusBadRequest, err.Error()) - } - if err = c.Validate(&req); err != nil { - return err - } - - pass, err := argon2id.CreateHash(req.Password, argon2id.DefaultParams) - if err != nil { - return echo.NewHTTPError(400, "Invalid password") - } - - duser, err := h.db.CreateUser(context.Background(), dbc.CreateUserParams{ - Username: req.Username, - Email: req.Email, - Password: &pass, - Claims: h.config.DefaultClaims, - }) - if err != nil { - return echo.NewHTTPError(409, "Email or username already taken") - } - user := MapDbUser(&duser) - return h.createToken(c, &user) -} - -func (h *Handler) createToken(c echo.Context, user *User) error { - claims := &jwt.RegisteredClaims{ - Subject: user.ID.String(), - } - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - t, err := token.SignedString(h.config.JwtSecret) - if err != nil { - return err - } - return c.JSON(http.StatusOK, echo.Map{ - "token": t, - }) -} diff --git a/auth/config.go b/auth/config.go index a8e16ae4..dc0cec14 100644 --- a/auth/config.go +++ b/auth/config.go @@ -5,12 +5,14 @@ import ( "crypto/rand" "encoding/base64" + "github.com/golang-jwt/jwt/v5" "github.com/zoriya/kyoo/keibi/dbc" ) type Configuration struct { JwtSecret []byte - DefaultClaims []byte + Issuer string + DefaultClaims jwt.MapClaims } const ( diff --git a/auth/main.go b/auth/main.go index 05aa37f2..2f1ce240 100644 --- a/auth/main.go +++ b/auth/main.go @@ -132,6 +132,7 @@ func main() { h.config = conf e.GET("/users", h.ListUsers) + e.POST("/users", h.Register) e.Logger.Fatal(e.Start(":4568")) } diff --git a/auth/session.go b/auth/session.go new file mode 100644 index 00000000..4c9011f4 --- /dev/null +++ b/auth/session.go @@ -0,0 +1,39 @@ +package main + +import ( + "maps" + "net/http" + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/labstack/echo/v4" +) + +type LoginDto struct { + Login string `json:"login" validate:"required"` + Password string `json:"password" validate:"required"` +} + +func (h *Handler) createToken(c echo.Context, user *User) error { + return nil +} + +func (h *Handler) CreateJwt(c echo.Context, user *User) error { + claims := maps.Clone(user.Claims) + claims["sub"] = user.ID.String() + claims["iss"] = h.config.Issuer + claims["exp"] = &jwt.NumericDate{ + Time: time.Now().UTC().Add(time.Hour), + } + claims["iss"] = &jwt.NumericDate{ + Time: time.Now().UTC(), + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + t, err := token.SignedString(h.config.JwtSecret) + if err != nil { + return err + } + return c.JSON(http.StatusOK, echo.Map{ + "token": t, + }) +} diff --git a/auth/sqlc.yaml b/auth/sqlc.yaml index e15d172e..75049429 100644 --- a/auth/sqlc.yaml +++ b/auth/sqlc.yaml @@ -19,5 +19,10 @@ sql: go_type: import: "github.com/google/uuid" type: "UUID" + - column: "users.claims" + go_type: + import: "github.com/golang-jwt/jwt/v5" + package: "jwt" + type: "MapClaims" diff --git a/auth/users.go b/auth/users.go index 02138620..4f8ed0d0 100644 --- a/auth/users.go +++ b/auth/users.go @@ -2,8 +2,11 @@ package main import ( "context" + "net/http" "time" + "github.com/alexedwards/argon2id" + "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" "github.com/labstack/echo/v4" "github.com/zoriya/kyoo/keibi/dbc" @@ -15,6 +18,7 @@ type User struct { Email string `json:"email"` CreatedDate time.Time `json:"createdDate"` LastSeen time.Time `json:"lastSeen"` + Claims jwt.MapClaims `json:"claims"` Oidc map[string]OidcHandle `json:"oidc,omitempty"` } @@ -24,6 +28,12 @@ type OidcHandle struct { ProfileUrl *string `json:"profileUrl"` } +type RegisterDto struct { + Username string `json:"username" validate:"required"` + Email string `json:"email" validate:"required,email"` + Password string `json:"password" validate:"required"` +} + func MapDbUser(user *dbc.User) User { return User{ ID: user.ID, @@ -31,6 +41,7 @@ func MapDbUser(user *dbc.User) User { Email: user.Email, CreatedDate: user.CreatedDate, LastSeen: user.LastSeen, + Claims: user.Claims, Oidc: nil, } } @@ -65,3 +76,31 @@ func (h *Handler) ListUsers(c echo.Context) error { } return c.JSON(200, ret) } + +func (h *Handler) Register(c echo.Context) error { + var req RegisterDto + err := c.Bind(&req) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, err.Error()) + } + if err = c.Validate(&req); err != nil { + return err + } + + pass, err := argon2id.CreateHash(req.Password, argon2id.DefaultParams) + if err != nil { + return echo.NewHTTPError(400, "Invalid password") + } + + duser, err := h.db.CreateUser(context.Background(), dbc.CreateUserParams{ + Username: req.Username, + Email: req.Email, + Password: &pass, + Claims: h.config.DefaultClaims, + }) + if err != nil { + return echo.NewHTTPError(409, "Email or username already taken") + } + user := MapDbUser(&duser) + return h.createToken(c, &user) +}