Skip to content

zoobz-io/sctx

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sctx

CI Status codecov Go Report Card CodeQL Go Reference License Go Version Release

Certificate-based security contexts for Go.

Turn mTLS certificates into typed authorization tokens with permissions, metadata, and delegatable guards.

Certificates Become Capabilities

Your PKI already establishes identity. sctx turns that identity into authorization.

// Define how certificates map to permissions
admin.SetPolicy(func(cert *x509.Certificate) (*sctx.Context[UserMeta], error) {
    return &sctx.Context[UserMeta]{
        Permissions: permissionsFromOU(cert.Subject.OrganizationalUnit),
        Metadata:    UserMeta{TenantID: cert.Subject.Organization[0]},
        ExpiresAt:   time.Now().Add(time.Hour),
    }, nil
})

// Client proves key possession, gets a signed token
assertion, _ := sctx.CreateAssertion(clientKey, clientCert)
token, _ := admin.Generate(ctx, clientCert, assertion)

// Token holder creates guards for specific permissions
guard, _ := admin.CreateGuard(ctx, token, "api:read", "api:write")

// Guards validate other tokens
err := guard.Validate(ctx, incomingToken)

No JWT parsing. No external identity provider. Your certificates are your identity system.

Install

go get github.com/zoobzio/sctx

Requires Go 1.24+.

Quick Start

package main

import (
    "context"
    "crypto/ed25519"
    "crypto/x509"
    "fmt"
    "time"

    "github.com/zoobzio/sctx"
)

type UserMeta struct {
    Role     string
    TenantID string
}

func main() {
    ctx := context.Background()

    // Create the admin service with your signing key and trusted CAs
    admin, _ := sctx.NewAdminService[UserMeta](privateKey, trustedCAPool)

    // Define authorization policy: certificate -> context
    admin.SetPolicy(func(cert *x509.Certificate) (*sctx.Context[UserMeta], error) {
        return &sctx.Context[UserMeta]{
            Permissions: []string{"read", "write"},
            Metadata:    UserMeta{Role: "admin", TenantID: cert.Subject.Organization[0]},
            ExpiresAt:   time.Now().Add(time.Hour),
        }, nil
    })

    // Client creates assertion proving key possession
    assertion, _ := sctx.CreateAssertion(clientKey, clientCert)

    // Admin generates signed token
    token, _ := admin.Generate(ctx, clientCert, assertion)

    // Create a guard for specific permissions
    guard, _ := admin.CreateGuard(ctx, token, "read")

    // Validate tokens against the guard
    if err := guard.Validate(ctx, token); err != nil {
        fmt.Println("Access denied:", err)
        return
    }

    fmt.Println("Access granted")
}

Capabilities

Feature Description Docs
Policy-Driven Authorization Transform certificates into contexts with custom policies Policy
Permission Guards Create guards that check for required permissions Guards
Type-Safe Metadata Generic contexts with compile-time type checking Concepts
Instant Revocation Revoke contexts by certificate fingerprint Revocation
Observability Capitan events for all operations Events
Testing Utilities Deterministic testing with mock certificates Testing

Why sctx?

  • Certificate-native — Built on mTLS, no separate identity layer
  • Type-safe — Generic metadata with compile-time checking
  • Delegatable — Token holders create guards for others to use
  • Zero shared secrets — Only public keys needed for validation
  • Instantly revocable — Revoke by fingerprint, all guards reject immediately
  • Observable — Every operation emits capitan events

PKI-Native Authorization

sctx enables a pattern: certificates establish identity, policies define permissions, guards enforce access.

Your mTLS infrastructure already verifies who clients are. sctx adds what they can do.

// In your mTLS handler — certificate is already verified
func handler(w http.ResponseWriter, r *http.Request) {
    cert := r.TLS.PeerCertificates[0]

    // Turn certificate into authorization token
    assertion, _ := sctx.CreateAssertion(clientKey, cert)
    token, _ := admin.Generate(r.Context(), cert, assertion)

    // Check permissions with a guard
    if err := readGuard.Validate(r.Context(), token); err != nil {
        http.Error(w, "Forbidden", http.StatusForbidden)
        return
    }

    // Authorized — proceed
}

One certificate, one policy, full authorization. No JWT middleware. No token introspection endpoints.

Documentation

  • Overview — Design philosophy and architecture

Learn

Guides

  • Policy — Certificate-to-context transformation
  • Guards — Permission checking and delegation
  • Events — Observability with capitan
  • Testing — Testing with mock certificates

Cookbook

Reference

  • API — Complete function documentation
  • Events — Capitan signal reference

Contributing

See CONTRIBUTING.md for guidelines. Run make help for available commands.

License

MIT License — see LICENSE for details.

About

Certificate-based security contexts for Go

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Contributors