Lock bootstrap admin token until password is changed.
Format / gofmt (push) Successful in 7s
CI / Build (push) Successful in 14s
Format / gofmt (pull_request) Successful in 7s
CI / Build (pull_request) Successful in 13s
CI / Go Tests (push) Successful in 50s
CI / Go Tests (pull_request) Successful in 48s

Closes #2: bootstrap JWTs cannot mutate admin APIs except change-password, production requires ADMIN_PASSWORD on first boot, admin binds loopback.
This commit is contained in:
s1d3sw1ped_bot
2026-09-01 03:54:09 +00:00
parent 6aabb76c16
commit 13070a275d
13 changed files with 445 additions and 40 deletions
+20 -8
View File
@@ -22,10 +22,11 @@ var (
// Claims for our JWT (minimal, matching original style).
type Claims struct {
UserID int `json:"user_id"`
Email string `json:"email"`
Name string `json:"name"`
Roles []string `json:"roles"`
UserID int `json:"user_id"`
Email string `json:"email"`
Name string `json:"name"`
Roles []string `json:"roles"`
Bootstrap bool `json:"bootstrap,omitempty"`
jwt.RegisteredClaims
}
@@ -95,15 +96,26 @@ func NewJWTManager(secret string) *JWTManager {
// GenerateToken creates a JWT for the given user (1 hour expiry like typical).
func (m *JWTManager) GenerateToken(userID int, email, name string, roles []string) (string, error) {
return m.signToken(userID, email, name, roles, false)
}
// GenerateBootstrapToken issues a JWT that cannot call mutating admin APIs
// until the default password has been changed.
func (m *JWTManager) GenerateBootstrapToken(userID int, email, name string, roles []string) (string, error) {
return m.signToken(userID, email, name, roles, true)
}
func (m *JWTManager) signToken(userID int, email, name string, roles []string, bootstrap bool) (string, error) {
now := time.Now()
if roles == nil {
roles = []string{}
}
claims := Claims{
UserID: userID,
Email: email,
Name: name,
Roles: roles,
UserID: userID,
Email: email,
Name: name,
Roles: roles,
Bootstrap: bootstrap,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(now.Add(1 * time.Hour)),
IssuedAt: jwt.NewNumericDate(now),