mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 19:43:04 +00:00
72 lines
2.2 KiB
Go
72 lines
2.2 KiB
Go
package auth
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// VerifyHandler verifies a wallet signature and issues JWT tokens and an API key.
|
|
// This completes the authentication flow by validating the signed nonce and returning
|
|
// access credentials.
|
|
//
|
|
// POST /v1/auth/verify
|
|
// Request body: VerifyRequest
|
|
// Response: { "access_token", "token_type", "expires_in", "refresh_token", "subject", "namespace", "api_key", "nonce", "signature_verified" }
|
|
func (h *Handlers) VerifyHandler(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 VerifyRequest
|
|
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)
|
|
|
|
token, refresh, expUnix, err := h.authService.IssueTokens(ctx, req.Wallet, req.Namespace)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
apiKey, err := h.authService.GetOrCreateAPIKey(ctx, req.Wallet, req.Namespace)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
"access_token": token,
|
|
"token_type": "Bearer",
|
|
"expires_in": int(expUnix - time.Now().Unix()),
|
|
"refresh_token": refresh,
|
|
"subject": req.Wallet,
|
|
"namespace": req.Namespace,
|
|
"api_key": apiKey,
|
|
"nonce": req.Nonce,
|
|
"signature_verified": true,
|
|
})
|
|
}
|