ProofedMesh/services/signing-service/internal/token/validator.go
CTO Agent d9fa1c55b9
All checks were successful
validate / Rego (opa fmt + opa test) (push) Successful in 14s
validate / JSON Schema (ajv) (push) Successful in 19s
validate / Go (vet + test) (push) Successful in 18s
services: add signing-service (real Ed25519 DSSE, in-memory keyring, AllowAll+Static validators as DEV; OpenBao/OPA/Pocket-ID as stubs). Interop with admin-api attest.HTTPSigner verified: 19 Go-Tests + end-to-end content_hash equality.
2026-10-25 18:02:44 +00:00

50 lines
1.4 KiB
Go

// Package token validates incoming Bearer tokens and extracts the subject
// (client agent identity). Prod uses Pocket ID JWKS; dev uses a static table.
package token
import (
"context"
"errors"
"net/http"
"strings"
)
// ErrInvalid is returned when a bearer token cannot be parsed or verified.
var ErrInvalid = errors.New("token: invalid or missing bearer token")
// Validator turns a raw bearer string into the authenticated client subject
// (the Pocket ID `sub` claim, i.e. the client/agent identity).
type Validator interface {
Validate(ctx context.Context, bearer string) (subject string, err error)
}
// Static is a dev-mode validator that accepts a fixed set of bearers → subjects.
type Static map[string]string
func (s Static) Validate(_ context.Context, bearer string) (string, error) {
if bearer == "" {
return "", ErrInvalid
}
sub, ok := s[bearer]
if !ok {
return "", ErrInvalid
}
return sub, nil
}
// PocketID is a stub for a JWKS-based Pocket ID token verifier.
type PocketID struct{}
func (PocketID) Validate(_ context.Context, _ string) (string, error) {
return "", errors.New("token.PocketID: not wired yet (follow-up subtask)")
}
// FromAuthHeader extracts the bearer from an "Authorization: Bearer …" header.
func FromAuthHeader(r *http.Request) (string, error) {
h := r.Header.Get("Authorization")
const prefix = "Bearer "
if !strings.HasPrefix(h, prefix) {
return "", ErrInvalid
}
return strings.TrimPrefix(h, prefix), nil
}