From 702fa6c37b9f74e75404a0ea8e6f9023841143de Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 14 Feb 2026 10:17:54 -0800 Subject: refactor: remove frivolous comments from auth and config Removed ~100 lines of obvious comments that just repeated what the code does. Kept only comments that add clarity or valuable detail. --- internal/auth/interceptor.go | 78 ++++++-------------------------------------- 1 file changed, 10 insertions(+), 68 deletions(-) (limited to 'internal/auth') diff --git a/internal/auth/interceptor.go b/internal/auth/interceptor.go index d394102..42c2688 100644 --- a/internal/auth/interceptor.go +++ b/internal/auth/interceptor.go @@ -11,52 +11,28 @@ import ( "google.golang.org/grpc/status" ) -// contextKey is a custom type for context keys to avoid collisions. type contextKey string const ( - // pubkeyContextKey is the key for storing the authenticated pubkey in context. pubkeyContextKey contextKey = "nostr-pubkey" ) -// InterceptorOptions configures the authentication interceptor behavior. type InterceptorOptions struct { - // Read configures authentication for read operations (Subscribe, QueryEvents, etc.) - Read OperationAuthConfig - - // Write configures authentication for write operations (PublishEvent, PublishBatch) - Write OperationAuthConfig - - // TimestampWindow is the maximum age of auth events in seconds. - // Events older than this are rejected to prevent replay attacks. - // Default: 60 seconds + Read OperationAuthConfig + Write OperationAuthConfig TimestampWindow int64 - - // ValidatePayload checks the payload hash tag if present. - // Default: false ValidatePayload bool - - // SkipMethods is a list of gRPC methods that bypass authentication. - // Useful for public endpoints like health checks or relay info. - // Example: []string{"/grpc.health.v1.Health/Check"} - // Default: nil (authenticate all methods) - SkipMethods []string + SkipMethods []string } -// OperationAuthConfig configures auth for a specific operation type. +// OperationAuthConfig configures auth for read or write operations. +// Three states: disabled (allow all), enabled with empty list (require auth), +// enabled with npubs (whitelist only). Npubs normalized to hex at load time. type OperationAuthConfig struct { - // Enabled determines if auth is required. - // false = no auth, allow all - // true = auth required - Enabled bool - - // AllowedNpubs is an optional whitelist (hex format, normalized from npub at config load). - // If Enabled=true && AllowedNpubs=[]: any valid signature accepted - // If Enabled=true && AllowedNpubs=[...]: only whitelisted npubs accepted + Enabled bool AllowedNpubs []string } -// DefaultInterceptorOptions returns the default configuration. func DefaultInterceptorOptions() *InterceptorOptions { return &InterceptorOptions{ Read: OperationAuthConfig{ @@ -73,19 +49,16 @@ func DefaultInterceptorOptions() *InterceptorOptions { } } -// NostrUnaryInterceptor creates a gRPC unary interceptor for NIP-98 authentication. func NostrUnaryInterceptor(opts *InterceptorOptions) grpc.UnaryServerInterceptor { if opts == nil { opts = DefaultInterceptorOptions() } return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - // Check if this method should skip auth if shouldSkipAuth(info.FullMethod, opts.SkipMethods) { return handler(ctx, req) } - // Check if auth is required for this operation type var authRequired bool if isWriteMethod(info.FullMethod) { authRequired = opts.Write.Enabled @@ -93,37 +66,31 @@ func NostrUnaryInterceptor(opts *InterceptorOptions) grpc.UnaryServerInterceptor authRequired = opts.Read.Enabled } - // If auth not required, skip validation if !authRequired { return handler(ctx, req) } - // Extract and validate auth pubkey, err := validateAuthFromContext(ctx, info.FullMethod, opts) if err != nil { return nil, status.Error(codes.Unauthenticated, err.Error()) } - // Add pubkey to context for handlers ctx = context.WithValue(ctx, pubkeyContextKey, pubkey) return handler(ctx, req) } } -// NostrStreamInterceptor creates a gRPC stream interceptor for NIP-98 authentication. func NostrStreamInterceptor(opts *InterceptorOptions) grpc.StreamServerInterceptor { if opts == nil { opts = DefaultInterceptorOptions() } return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { - // Check if this method should skip auth if shouldSkipAuth(info.FullMethod, opts.SkipMethods) { return handler(srv, ss) } - // Check if auth is required for this operation type var authRequired bool if isWriteMethod(info.FullMethod) { authRequired = opts.Write.Enabled @@ -131,19 +98,16 @@ func NostrStreamInterceptor(opts *InterceptorOptions) grpc.StreamServerIntercept authRequired = opts.Read.Enabled } - // If auth not required, skip validation if !authRequired { return handler(srv, ss) } - // Extract and validate auth ctx := ss.Context() pubkey, err := validateAuthFromContext(ctx, info.FullMethod, opts) if err != nil { return status.Error(codes.Unauthenticated, err.Error()) } - // Wrap stream with authenticated context wrappedStream := &authenticatedStream{ ServerStream: ss, ctx: context.WithValue(ctx, pubkeyContextKey, pubkey), @@ -153,8 +117,7 @@ func NostrStreamInterceptor(opts *InterceptorOptions) grpc.StreamServerIntercept } } -// authenticatedStream wraps a ServerStream with an authenticated context. -type authenticatedStream struct { +type authenticatedStream struct{ grpc.ServerStream ctx context.Context } @@ -163,45 +126,34 @@ func (s *authenticatedStream) Context() context.Context { return s.ctx } -// validateAuthFromContext extracts and validates the NIP-98 auth event from the context. func validateAuthFromContext(ctx context.Context, method string, opts *InterceptorOptions) (string, error) { - // Extract metadata from context md, ok := metadata.FromIncomingContext(ctx) if !ok { return "", fmt.Errorf("missing metadata") } - // Get authorization header authHeaders := md.Get("authorization") if len(authHeaders) == 0 { return "", fmt.Errorf("missing authorization header") } - authHeader := authHeaders[0] - - // Parse the auth event - event, err := ParseAuthHeader(authHeader) + event, err := ParseAuthHeader(authHeaders[0]) if err != nil { return "", fmt.Errorf("invalid auth header: %w", err) } - // Validate the event validationOpts := ValidationOptions{ TimestampWindow: opts.TimestampWindow, ValidatePayload: opts.ValidatePayload, - ExpectedMethod: "POST", // gRPC always uses POST - // Note: We don't validate URI here because the full URI isn't easily - // available in the interceptor context. The method name is validated instead. + ExpectedMethod: "POST", } if err := ValidateAuthEvent(event, validationOpts); err != nil { return "", fmt.Errorf("invalid auth event: %w", err) } - // Extract pubkey pubkey := ExtractPubkey(event) - // Get the operation config based on method type var opConfig OperationAuthConfig if isWriteMethod(method) { opConfig = opts.Write @@ -209,7 +161,6 @@ func validateAuthFromContext(ctx context.Context, method string, opts *Intercept opConfig = opts.Read } - // Check whitelist if configured if len(opConfig.AllowedNpubs) > 0 { if !contains(opConfig.AllowedNpubs, pubkey) { if isWriteMethod(method) { @@ -219,18 +170,13 @@ func validateAuthFromContext(ctx context.Context, method string, opts *Intercept } } - // No whitelist or pubkey in whitelist - allow return pubkey, nil } -// isWriteMethod determines if a gRPC method is a write operation. -// Write: PublishEvent, PublishBatch -// Read: Subscribe, Unsubscribe, QueryEvents, CountEvents func isWriteMethod(method string) bool { return strings.Contains(method, "/PublishEvent") || strings.Contains(method, "/PublishBatch") } -// shouldSkipAuth checks if a method should bypass authentication. func shouldSkipAuth(method string, skipMethods []string) bool { for _, skip := range skipMethods { if skip == method { @@ -240,7 +186,6 @@ func shouldSkipAuth(method string, skipMethods []string) bool { return false } -// contains checks if a slice contains a string. func contains(slice []string, item string) bool { for _, s := range slice { if s == item { @@ -250,14 +195,11 @@ func contains(slice []string, item string) bool { return false } -// PubkeyFromContext retrieves the authenticated pubkey from the context. -// Returns the pubkey and true if authentication was successful, or empty string and false otherwise. func PubkeyFromContext(ctx context.Context) (string, bool) { pubkey, ok := ctx.Value(pubkeyContextKey).(string) return pubkey, ok } -// RequireAuth is a helper that extracts the pubkey and returns an error if not authenticated. func RequireAuth(ctx context.Context) (string, error) { pubkey, ok := PubkeyFromContext(ctx) if !ok || pubkey == "" { -- cgit v1.2.3