Documentation
¶
Overview ¶
Package jwt provides JWT authentication bundle for secure inter-service communication.
The JWT bundle provides:
- JWT token validation and signing
- gRPC authentication interceptors for both client and server
- HTTP authentication middleware
- Token propagation between services
- Service identity management
- Configurable token validation (expiry, audience, issuer)
Basic Usage ¶
Configure JWT authentication for your service:
jwtConfig := jwt.Config{
SecretKey: []byte("your-secret-key"),
Issuer: "auth-service",
Audience: "forge-services",
TokenDuration: 24 * time.Hour,
ServiceName: "user-service",
}
jwtBundle := jwt.NewBundle(jwtConfig)
app, err := framework.New(
framework.WithConfig(&baseConfig),
framework.WithBundle(jwtBundle),
)
Service-to-Service Authentication ¶
The bundle automatically adds authentication to gRPC calls:
// Client side (automatic token injection)
conn, err := grpc.Dial("target-service:8080",
grpc.WithUnaryInterceptor(jwtBundle.UnaryClientInterceptor()),
)
// Server side (automatic token validation)
app, err := framework.New(
framework.WithUnaryInterceptor(jwtBundle.UnaryServerInterceptor()),
framework.WithStreamInterceptor(jwtBundle.StreamServerInterceptor()),
)
The framework maintains separate interceptor chains for unary and streaming RPCs. Registering only UnaryServerInterceptor leaves server-streaming and bidirectional-streaming methods completely unauthenticated — always register both interceptors together.
HTTP Authentication ¶
Secure HTTP endpoints with JWT middleware:
// Protect specific endpoints
protectedMux := http.NewServeMux()
protectedMux.HandleFunc("/api/users", userHandler)
// Apply JWT middleware
http.Handle("/api/", jwtBundle.HTTPMiddleware(protectedMux))
Token Claims ¶
Access authenticated service information in handlers:
func userHandler(ctx context.Context, req *UserRequest) (*UserResponse, error) {
claims := jwt.ClaimsFromContext(ctx)
if claims == nil {
return nil, status.Errorf(codes.Unauthenticated, "no authentication")
}
serviceID := claims.ServiceID
// ... use service identity for authorization
}
Index ¶
- func HasPermission(ctx context.Context, permission string) bool
- func ServiceID(ctx context.Context) string
- func ServiceName(ctx context.Context) string
- type Bundle
- func (b *Bundle) GenerateServiceToken(permissions []string) (string, error)
- func (b *Bundle) GenerateToken(serviceID, serviceName string, permissions []string) (string, error)
- func (b *Bundle) HTTPMiddleware(next http.Handler) http.Handler
- func (b *Bundle) Initialize(app *framework.App) error
- func (b *Bundle) Name() string
- func (b *Bundle) RequirePermissions(permissions ...string) func(http.Handler) http.Handler
- func (b *Bundle) Stop(ctx context.Context) error
- func (b *Bundle) StreamServerInterceptor() grpc.StreamServerInterceptor
- func (b *Bundle) UnaryClientInterceptor() grpc.UnaryClientInterceptor
- func (b *Bundle) UnaryServerInterceptor() grpc.UnaryServerInterceptor
- func (b *Bundle) ValidateToken(tokenString string) (*ServiceClaims, error)
- type Config
- type ServiceClaims
- type TokenValidator
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func HasPermission ¶
HasPermission checks if the authenticated service has the specified permission.
func ServiceID ¶ added in v0.3.0
ServiceID extracts the caller's service ID from a context that the JWT server interceptor (or HTTP middleware) previously populated with validated claims. It returns the empty string when the context carries no claims, so callers can use it for logging or coarse authorization without a nil check.
func ServiceName ¶ added in v0.3.0
ServiceName extracts the caller's service name from a context that the JWT server interceptor (or HTTP middleware) previously populated with validated claims. It returns the empty string when the context carries no claims, so callers can use it for logging or coarse authorization without a nil check.
Types ¶
type Bundle ¶
type Bundle struct {
// contains filtered or unexported fields
}
Bundle provides JWT authentication for Forge applications.
func (*Bundle) GenerateServiceToken ¶
GenerateServiceToken creates a token for this service to authenticate with other services.
func (*Bundle) GenerateToken ¶
GenerateToken creates a new JWT token for service-to-service communication.
func (*Bundle) HTTPMiddleware ¶
HTTPMiddleware returns HTTP middleware for JWT authentication.
func (*Bundle) Initialize ¶
Initialize validates the JWT configuration during application startup. The bundle holds no external resources, so no connections are opened here; the interceptors and middleware it exposes must be wired into the framework explicitly by the caller.
func (*Bundle) RequirePermissions ¶
RequirePermissions returns middleware that requires specific permissions.
func (*Bundle) Stop ¶
Stop implements the Bundle interface for graceful shutdown. JWT bundle has no persistent resources requiring cleanup.
func (*Bundle) StreamServerInterceptor ¶ added in v0.3.0
func (b *Bundle) StreamServerInterceptor() grpc.StreamServerInterceptor
StreamServerInterceptor returns a gRPC stream server interceptor for JWT authentication. It performs the same token extraction and validation as UnaryServerInterceptor, but reads the token from the stream's context (grpc.ServerStream.Context()) and injects claims into a wrapped stream so handlers can retrieve them via ClaimsFromContext.
func (*Bundle) UnaryClientInterceptor ¶
func (b *Bundle) UnaryClientInterceptor() grpc.UnaryClientInterceptor
UnaryClientInterceptor returns a gRPC client interceptor for JWT token injection.
func (*Bundle) UnaryServerInterceptor ¶
func (b *Bundle) UnaryServerInterceptor() grpc.UnaryServerInterceptor
UnaryServerInterceptor returns a gRPC server interceptor for JWT authentication.
func (*Bundle) ValidateToken ¶
func (b *Bundle) ValidateToken(tokenString string) (*ServiceClaims, error)
ValidateToken validates a JWT token and returns the claims.
type Config ¶
type Config struct {
// SecretKey is the HMAC secret key for signing and validating tokens.
// This should be a strong, random key shared across all services.
SecretKey []byte
// Issuer is the JWT issuer claim (typically your auth service).
Issuer string
// Audience is the JWT audience claim (typically your service mesh or organization).
Audience string
// TokenDuration is how long tokens remain valid.
TokenDuration time.Duration
// ServiceName is the name of this service (used in service-to-service tokens).
ServiceName string
// ClockSkew is the allowed time difference when validating token timestamps.
ClockSkew time.Duration
// RequireHTTPS enforces HTTPS for HTTP authentication (recommended for production).
RequireHTTPS bool
// TrustedProxyHeader controls whether the X-Forwarded-Proto header is
// trusted to satisfy RequireHTTPS. It defaults to false: by default only
// the actual connection (req.TLS != nil) is consulted, since any client
// can forge X-Forwarded-Proto. Set this to true only when the service
// sits behind a trusted, terminating reverse proxy that overwrites (never
// merely appends to) this header before requests reach the service.
TrustedProxyHeader bool
// SkipPaths are HTTP paths that don't require authentication.
SkipPaths []string
}
Config contains JWT authentication configuration.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns a Config with sensible secure defaults.
type ServiceClaims ¶
type ServiceClaims struct {
jwt.RegisteredClaims
ServiceID string `json:"service_id"`
ServiceName string `json:"service_name"`
Permissions []string `json:"permissions,omitempty"`
}
ServiceClaims represents the claims in a service-to-service JWT token.
func ClaimsFromContext ¶
func ClaimsFromContext(ctx context.Context) *ServiceClaims
ClaimsFromContext extracts JWT claims from the context.
type TokenValidator ¶
type TokenValidator interface {
// ValidateToken applies custom validation to already-parsed claims and
// returns a non-nil error to reject the token.
ValidateToken(ctx context.Context, claims *ServiceClaims) error
}
TokenValidator provides an interface for custom token validation logic. Implementations can enforce application-specific rules (for example revocation checks or per-tenant policy) on top of the bundle's standard signature, expiry, audience, and issuer validation.