package auth import ( "encoding/json" "fmt" "net/http" "strings" authsvc "github.com/DeBrosOfficial/network/pkg/gateway/auth" ) // WhoamiHandler returns the authenticated user's identity and method. // This endpoint shows whether the request is authenticated via JWT or API key, // and provides details about the authenticated principal. // // GET /v1/auth/whoami // Response: { "authenticated", "method", "subject", "namespace", ... } func (h *Handlers) WhoamiHandler(w http.ResponseWriter, r *http.Request) { ctx := r.Context() // Determine namespace (may be overridden by auth layer) ns := h.defaultNS if v := ctx.Value(CtxKeyNamespaceOverride); v != nil { if s, ok := v.(string); ok && s != "" { ns = s } } // Prefer JWT if present if v := ctx.Value(CtxKeyJWT); v != nil { if claims, ok := v.(*authsvc.JWTClaims); ok && claims != nil { writeJSON(w, http.StatusOK, map[string]any{ "authenticated": true, "method": "jwt", "subject": claims.Sub, "issuer": claims.Iss, "audience": claims.Aud, "issued_at": claims.Iat, "not_before": claims.Nbf, "expires_at": claims.Exp, "namespace": ns, }) return } } // Fallback: API key identity var key string if v := ctx.Value(CtxKeyAPIKey); v != nil { if s, ok := v.(string); ok { key = s } } writeJSON(w, http.StatusOK, map[string]any{ "authenticated": key != "", "method": "api_key", "api_key": key, "namespace": ns, }) } // RegisterHandler registers a new application/client after wallet signature verification. // This allows wallets to register applications and obtain client credentials. // // POST /v1/auth/register // Request body: RegisterRequest // Response: { "client_id", "app": { ... }, "signature_verified" } func (h *Handlers) RegisterHandler(w http.ResponseWriter, r *http.Request) { if h.authService == nil { writeError(w, http.StatusServiceUnavailable, "auth service not initialized") return } if r.Method != http.MethodPost { writeError(w, http.StatusMethodNotAllowed, "method not allowed") return } var req RegisterRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid json body") return } if strings.TrimSpace(req.Wallet) == "" || strings.TrimSpace(req.Nonce) == "" || strings.TrimSpace(req.Signature) == "" { writeError(w, http.StatusBadRequest, "wallet, nonce and signature are required") return } ctx := r.Context() verified, err := h.authService.VerifySignature(ctx, req.Wallet, req.Nonce, req.Signature, req.ChainType) if err != nil || !verified { writeError(w, http.StatusUnauthorized, "signature verification failed") return } // Mark nonce used nsID, _ := h.resolveNamespace(ctx, req.Namespace) h.markNonceUsed(ctx, nsID, strings.ToLower(req.Wallet), req.Nonce) // In a real app we'd derive the public key from the signature, but for simplicity here // we just use a placeholder or expect it in the request if needed. // For Ethereum, we can recover it. publicKey := "recovered-pk" appID, err := h.authService.RegisterApp(ctx, req.Wallet, req.Namespace, req.Name, publicKey) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusCreated, map[string]any{ "client_id": appID, "app": map[string]any{ "app_id": appID, "name": req.Name, "namespace": req.Namespace, "wallet": strings.ToLower(req.Wallet), }, "signature_verified": true, }) } // LoginPageHandler serves the wallet authentication login page. // This provides an interactive HTML page for wallet-based authentication // using MetaMask or other Web3 wallet providers. // // GET /v1/auth/login?callback= // Query params: callback (required) - URL to redirect after successful auth // Response: HTML page with wallet connection UI func (h *Handlers) LoginPageHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { writeError(w, http.StatusMethodNotAllowed, "method not allowed") return } callbackURL := r.URL.Query().Get("callback") if callbackURL == "" { writeError(w, http.StatusBadRequest, "callback parameter is required") return } // Get default namespace ns := strings.TrimSpace(h.defaultNS) if ns == "" { ns = "default" } w.Header().Set("Content-Type", "text/html") w.WriteHeader(http.StatusOK) html := fmt.Sprintf(` DeBros Network - Wallet Authentication

Secure Wallet Authentication

📁 Namespace: %s
1Connect Your Wallet

Click the button below to connect your Ethereum wallet (MetaMask, WalletConnect, etc.)

2Sign Authentication Message

Your wallet will prompt you to sign a message to prove your identity. This is free and secure.

3Get Your API Key

After signing, you'll receive an API key to access the DeBros Network.

Processing authentication...

`, ns, callbackURL, ns) fmt.Fprint(w, html) }