feat(security): send request info as login claims

Add RequestInfoMiddleware / WithRequestInfo, which put client details in the
context. Login, LoginWithAPIKey, LoginWithPasskey and JWT login merge them into
the claims: ip_address, client_port, is_private_ip, previous_session, device_id,
client_id, user_agent, server_ip_address, server_port, host, origin, referer.
RequestInfoOptions adds trusted-proxy handling for X-Forwarded-For/X-Real-IP.
This commit is contained in:
Hein
2026-10-12 12:18:23 +02:00
parent 5b6406ef38
commit fbfc1aadb5
4 changed files with 466 additions and 2 deletions
+4 -2
View File
@@ -170,6 +170,7 @@ func (a *DatabaseAuthenticator) SetAuthenticateCallback(fn func(r *http.Request)
}
func (a *DatabaseAuthenticator) Login(ctx context.Context, req LoginRequest) (*LoginResponse, error) {
req.Claims = enrichClaims(ctx, req.Claims)
return a.auth().Login(ctx, req)
}
@@ -179,7 +180,7 @@ func (a *DatabaseAuthenticator) Login(ctx context.Context, req LoginRequest) (*L
// Procedure-only: the key and user lookup live in resolvespec_login_api_key so
// the underlying schema can differ per database; there is no direct-SQL path.
func (a *DatabaseAuthenticator) LoginWithAPIKey(ctx context.Context, rawKey string, claims map[string]any) (*LoginResponse, error) {
return a.auth().LoginAPIKey(ctx, rawKey, claims)
return a.auth().LoginAPIKey(ctx, rawKey, enrichClaims(ctx, claims))
}
// Register implements Registrable interface
@@ -403,6 +404,7 @@ func (a *JWTAuthenticator) WithLookupProvider(p *lookup.Provider) *JWTAuthentica
func (a *JWTAuthenticator) auth() lookup.AuthStore { return a.src.get().Auth }
func (a *JWTAuthenticator) Login(ctx context.Context, req LoginRequest) (*LoginResponse, error) {
req.Claims = enrichClaims(ctx, req.Claims)
return a.auth().JWTLogin(ctx, req)
}
@@ -626,7 +628,7 @@ func (a *DatabaseAuthenticator) LoginWithPasskey(ctx context.Context, req Passke
return nil, fmt.Errorf("passkey authentication failed: %w", err)
}
return a.src.get().Passkey.Login(ctx, userID, req.Claims)
return a.src.get().Passkey.Login(ctx, userID, enrichClaims(ctx, req.Claims))
}
// GetPasskeyCredentials returns all passkey credentials for a user