Client-seitige Token-Generierung
#
Installation
#
go get github.com/SecureWebhookToken/swt@v0.4.0
Grundlegende Token-Erstellung und -Versand
#
package main
import (
"fmt"
"log"
"net/http"
"github.com/SecureWebhookToken/swt"
)
func main() {
secretKey := []byte("your-secret-key-min-256-bits")
// Webhook-Request mit Payload erstellen
req := &swt.Request{
URL: "https://api.example.com/webhook",
Issuer: "webhook-service.example.com",
Event: "user.created",
HashAlg: swt.SHA256, // Optional: Standard ist SHA-256
Data: []byte(`{"userId":"12345","email":"user@example.com"}`),
}
// HTTP-Request mit eingebettetem SWT-Token erstellen
httpReq, err := req.Build(secretKey)
if err != nil {
log.Fatalf("Request-Erstellung fehlgeschlagen: %v", err)
}
// Request senden
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
log.Fatalf("Request-Versand fehlgeschlagen: %v", err)
}
defer resp.Body.Close()
fmt.Printf("Response-Status: %s\n", resp.Status)
}
Token-Erstellung mit leerem Body
#
package main
import (
"fmt"
"log"
"net/http"
"github.com/SecureWebhookToken/swt"
)
func main() {
secretKey := []byte("your-secret-key-min-256-bits")
// Webhook-Request ohne Payload erstellen (leerer Body)
req := &swt.Request{
URL: "https://api.example.com/webhook",
Issuer: "webhook-service.example.com",
Event: "health.check",
Data: nil, // Keine Payload
}
httpReq, err := req.Build(secretKey)
if err != nil {
log.Fatalf("Request-Erstellung fehlgeschlagen: %v", err)
}
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
log.Fatalf("Request-Versand fehlgeschlagen: %v", err)
}
defer resp.Body.Close()
fmt.Printf("Health-Check-Response: %s\n", resp.Status)
}
Erweiterte Token-Erstellung mit Optionen
#
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/SecureWebhookToken/swt"
"github.com/google/uuid"
)
func main() {
secretKey := []byte("your-secret-key-min-256-bits")
// Token mit benutzerdefinierten Optionen erstellen
req := &swt.Request{
URL: "https://api.example.com/webhook",
Issuer: "webhook-service.example.com",
Event: "payment.received",
HashAlg: swt.SHA384, // SHA-384 statt Standard SHA-256 verwenden
Data: []byte(`{"amount":100.00,"currency":"USD"}`),
}
// Mit benutzerdefinierten Optionen erstellen
ctx := context.Background()
httpReq, err := req.BuildWithContext(ctx, secretKey,
swt.WithID(uuid.New().String()), // Benutzerdefinierte JWT-ID
swt.WithSubject("user-12345"), // Subject-Identifikator
swt.WithExpiresAt(time.Now().Add(5*time.Minute)), // 5 Minuten Gültigkeit
swt.WithNotBefore(time.Now()), // Sofort gültig
swt.WithRetryCount(0), // Erster Zustellungsversuch
)
if err != nil {
log.Fatalf("Request-Erstellung fehlgeschlagen: %v", err)
}
client := &http.Client{}
resp, err := client.Do(httpReq)
if err != nil {
log.Fatalf("Request-Versand fehlgeschlagen: %v", err)
}
defer resp.Body.Close()
fmt.Printf("Payment-Webhook gesendet: %s\n", resp.Status)
}
Token manuell erstellen (Low-level API)
#
package main
import (
"fmt"
"log"
"time"
"github.com/SecureWebhookToken/swt"
"github.com/google/uuid"
)
func main() {
secretKey := []byte("your-secret-key-min-256-bits")
// Hash für die Payload erstellen
payload := []byte(`{"userId":"12345"}`)
hash := swt.NewHash(swt.SHA256, payload)
// Token mit Event und Hash erstellen
token, err := swt.New(
"webhook-service.example.com", // Issuer
"user.created", // Event
hash, // Payload-Hash
swt.WithID(uuid.New().String()),
swt.WithExpiresAt(time.Now().Add(5*time.Minute)),
swt.WithNotBefore(time.Now()),
swt.WithSubject("user-12345"),
)
if err != nil {
log.Fatalf("Token-Erstellung fehlgeschlagen: %v", err)
}
// Token signieren
tokenString, err := token.SignedString(secretKey)
if err != nil {
log.Fatalf("Token-Signierung fehlgeschlagen: %v", err)
}
fmt.Printf("Token: %s\n", tokenString)
fmt.Printf("Event: %s\n", token.Webhook().Event)
fmt.Printf("Hash: %s\n", token.Webhook().Hash.String())
}
Retry-Logik mit Retry-Count
#
package main
import (
"fmt"
"log"
"net/http"
"time"
"github.com/SecureWebhookToken/swt"
)
func sendWebhookWithRetry(req *swt.Request, secretKey []byte, maxRetries uint) error {
client := &http.Client{Timeout: 30 * time.Second}
for retry := uint(0); retry <= maxRetries; retry++ {
// Request mit aktuellem Retry-Count erstellen
httpReq, err := req.Build(secretKey, swt.WithRetryCount(retry))
if err != nil {
return fmt.Errorf("Request-Erstellung fehlgeschlagen: %w", err)
}
resp, err := client.Do(httpReq)
if err != nil {
log.Printf("Versuch %d fehlgeschlagen: %v", retry, err)
if retry < maxRetries {
time.Sleep(time.Duration(retry+1) * 2 * time.Second) // Exponentieller Backoff
continue
}
return fmt.Errorf("alle Wiederholungsversuche fehlgeschlagen: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
fmt.Printf("Webhook erfolgreich zugestellt bei Versuch %d\n", retry)
return nil
}
log.Printf("Versuch %d ergab Status %d", retry, resp.StatusCode)
if retry < maxRetries {
time.Sleep(time.Duration(retry+1) * 2 * time.Second)
}
}
return fmt.Errorf("Webhook-Zustellung fehlgeschlagen nach %d Versuchen", maxRetries)
}
func main() {
secretKey := []byte("your-secret-key-min-256-bits")
req := &swt.Request{
URL: "https://api.example.com/webhook",
Issuer: "webhook-service.example.com",
Event: "order.completed",
Data: []byte(`{"orderId":"ORD-12345","total":250.00}`),
}
if err := sendWebhookWithRetry(req, secretKey, 3); err != nil {
log.Fatalf("Webhook-Zustellung fehlgeschlagen: %v", err)
}
}