diff --git a/auth/README.md b/auth/README.md index 12391e4d..0b446249 100644 --- a/auth/README.md +++ b/auth/README.md @@ -61,11 +61,11 @@ GET `/users/$id/sessions` can be used by admins to list others session ``` Get `/apikeys` -Post `/apikeys` {...nlaims} Create a new api keys with given claims +Post `/apikeys` {...claims} Create a new api keys with given claims ``` An api key can be used like an opaque token, calling /jwt with it will return a valid jwt with the claims you specified during the post request to create it. -Creating an apikeys requires the `apikey.create` permission, reading them requires the `apikey.read` permission. +Creating an apikeys requires the `apikey.write` permission, reading them requires the `apikey.read` permission. ### OIDC diff --git a/auth/apikey.go b/auth/apikey.go new file mode 100644 index 00000000..c73375e4 --- /dev/null +++ b/auth/apikey.go @@ -0,0 +1,44 @@ +package main + +import ( + "net/http" + "time" + + "github.com/golang-jwt/jwt/v5" + "github.com/labstack/echo/v4" +) + +type ApiKey struct { + Name string `json:"name" example:"my-app"` + Token string `json:"token" example:"lyHzTYm9yi+pkEv3m2tamAeeK7Dj7N3QRP7xv7dPU5q9MAe8tU4ySwYczE0RaMr4fijsA=="` + CreatedAt time.Time `json:"createAt" example:"2025-03-29T18:20:05.267Z"` + LastUsed time.Time `json:"lastUsed" example:"2025-03-29T18:20:05.267Z"` + Claims jwt.MapClaims `json:"claims" example:"isAdmin: true"` +} + +type ApiKeyDto struct { + Name string `json:"name" example:"my-app" validate:"alpha"` + Claims jwt.MapClaims `json:"claims" example:"isAdmin: true"` +} + +// @Summary Create API key +// @Description Create a new API key +// @Tags apikeys +// @Accept json +// @Produce json +// @Security Jwt[apikeys.write] +// @Param key body ApiKeyDto false "Api key info" +// @Success 201 {object} ApiKey +// @Failure 409 {object} KError "Duplicated api key" +// @Failure 422 {object} KError "Invalid create body" +// @Router /users [get] +func (h *Handler) CreateApiKey(c echo.Context) error { + var req ApiKeyDto + err := c.Bind(&req) + if err != nil { + return echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error()) + } + if err = c.Validate(&req); err != nil { + return err + } +} diff --git a/auth/sql/migrations/000003_apikeys.down.sql b/auth/sql/migrations/000003_apikeys.down.sql new file mode 100644 index 00000000..3bdbcde3 --- /dev/null +++ b/auth/sql/migrations/000003_apikeys.down.sql @@ -0,0 +1,5 @@ +begin; + +drop table apikeys; + +commit; diff --git a/auth/sql/migrations/000003_apikeys.up.sql b/auth/sql/migrations/000003_apikeys.up.sql new file mode 100644 index 00000000..cb333485 --- /dev/null +++ b/auth/sql/migrations/000003_apikeys.up.sql @@ -0,0 +1,14 @@ +begin; + +create table apikeys( + pk serial primary key, + id uuid not null default gen_random_uuid(), + name varchar(256) not null unique, + token varchar(128) not null unique, + claims jsonb not null, + + created_at timestamptz not null default now()::timestamptz, + last_used timestamptz not null default now()::temistamptz +); + +commit;