Frontend Labs
⋯

Week 6 Mini Project: mTLS Service Gateway

Build a complete service gateway: mTLS client authentication + ECDSA token issuance + upstream forwarding.

// gateway/main.go
package main

import (
    "crypto/tls"
    "fmt"
    "net/http"
    "net/http/httputil"
    "net/url"
    "time"
)

func main() {
    // Load PKI (generated in Day 40)
    tlsConfig, err := buildMTLSServerConfig("server.crt", "server.key", "ca.crt")
    if err != nil { fmt.Println(err); return }

    tokenService, err := NewTokenService() // from Day 44
    if err != nil { fmt.Println(err); return }

    upstream, _ := url.Parse("http://127.0.0.1:9090")
    proxy := httputil.NewSingleHostReverseProxy(upstream)

    mux := http.NewServeMux()

    // Auth endpoint: validates mTLS, issues ECDSA token
    mux.HandleFunc("POST /auth/token", func(w http.ResponseWriter, r *http.Request) {
        identity := clientIdentityFromRequest(r)
        if identity == "" {
            http.Error(w, "client certificate required", http.StatusUnauthorized)
            return
        }

        token, err := tokenService.Issue(identity, []string{"read", "write"})
        if err != nil {
            http.Error(w, "token issue error", 500)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintf(w, `{"token":%q,"expires_in":3600}`, token)
    })

    // Protected API: validate ECDSA token, inject identity header, proxy
    mux.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
        authHeader := r.Header.Get("Authorization")
        if len(authHeader) < 8 || authHeader[:7] != "Bearer " {
            http.Error(w, "authorization required", http.StatusUnauthorized)
            return
        }

        claims, err := tokenService.Verify(authHeader[7:])
        if err != nil {
            http.Error(w, "invalid token", http.StatusUnauthorized)
            return
        }

        // Inject verified identity for upstream service
        r.Header.Set("X-Authenticated-Subject", claims.Subject)
        r.Header.Del("Authorization") // don't forward token to upstream

        proxy.ServeHTTP(w, r)
    })

    srv := &http.Server{
        Addr:              ":8443",
        Handler:           mux,
        TLSConfig:         tlsConfig,
        ReadHeaderTimeout: 5 * time.Second,
    }

    fmt.Println("mTLS gateway on :8443")
    fmt.Println("1. Get token: curl --cert client.crt --key client.key --cacert ca.crt https://localhost:8443/auth/token -X POST")
    fmt.Println("2. Use token: curl --cacert ca.crt -H 'Authorization: Bearer <token>' https://localhost:8443/api/data")

    srv.ListenAndServeTLS("", "")
}

Engineer Takeaway

This is the core of a zero-trust service-to-service auth system. Istio, SPIFFE, and AWS Private CA all implement this pattern. You've built it from scratch in ~200 lines. The X-Authenticated-Subject header is how your backend services know who is calling them — without managing API keys or shared secrets.

Generated from week6.md · 8 Oct 2026 16:36