This commit is contained in:
Tomas Dvorak
2026-05-05 09:48:07 +02:00
parent d854614a87
commit 48c3e15a38
295 changed files with 178381 additions and 1039 deletions
+16 -1
View File
@@ -12,8 +12,23 @@ import (
const principalContextKey = "principal"
func RequireAuth(verifier *Verifier, repo db.Repository) gin.HandlerFunc {
// DemoPrincipal is the auto-authenticated user in demo mode
var DemoPrincipal = domain.Principal{
Subject: "demo-owner",
Email: "demo@bookra.dev",
Name: "Demo User",
Role: "owner",
}
func RequireAuth(verifier *Verifier, repo db.Repository, demoMode bool) gin.HandlerFunc {
return func(c *gin.Context) {
// In demo mode, auto-authenticate as the demo user
if demoMode {
c.Set(principalContextKey, DemoPrincipal)
c.Next()
return
}
if verifier == nil || !verifier.Enabled() {
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "auth_not_configured"})
return
+29 -3
View File
@@ -16,13 +16,18 @@ type Verifier struct {
jwks keyfunc.Keyfunc
expectedIssuer string
enabled bool
localSecret []byte
cancel context.CancelFunc
}
func NewVerifier(neonAuthURL string) (*Verifier, error) {
trimmed := strings.TrimSpace(neonAuthURL)
func NewVerifier(neonAuthURL string, localJWTSecret string) (*Verifier, error) {
trimmed := strings.TrimRight(strings.TrimSpace(neonAuthURL), "/")
if trimmed == "" {
return &Verifier{enabled: false}, nil
secret := strings.TrimSpace(localJWTSecret)
return &Verifier{
enabled: secret != "",
localSecret: []byte(secret),
}, nil
}
parsed, err := url.Parse(trimmed)
@@ -45,6 +50,7 @@ func NewVerifier(neonAuthURL string) (*Verifier, error) {
jwks: jwks,
expectedIssuer: expectedIssuer,
enabled: true,
localSecret: []byte(strings.TrimSpace(localJWTSecret)),
cancel: cancel,
}, nil
}
@@ -64,6 +70,26 @@ func (v *Verifier) Verify(tokenString string) (jwt.MapClaims, error) {
return nil, errors.New("neon auth verifier is disabled")
}
if len(v.localSecret) > 0 && v.jwks == nil {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return v.localSecret, nil
}, jwt.WithIssuer("bookra-auth"), jwt.WithAudience("bookra"), jwt.WithLeeway(15*time.Second))
if err != nil {
return nil, err
}
claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid {
return nil, errors.New("invalid token claims")
}
if tokenType, _ := claims["type"].(string); tokenType != "access" {
return nil, errors.New("invalid token type")
}
return claims, nil
}
token, err := jwt.Parse(tokenString, v.jwks.Keyfunc,
jwt.WithIssuer(v.expectedIssuer),
jwt.WithValidMethods([]string{"EdDSA"}),