Skip to content

Commit 1062fb3

Browse files
committed
Initial commit
0 parents  commit 1062fb3

405 files changed

Lines changed: 19353 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# IDE specific
2+
.idea/
3+
4+
### Hugo template
5+
# Generated files by hugo
6+
/resources/_gen/
7+
/assets/jsconfig.json
8+
hugo_stats.json
9+
10+
# Executable may be added to repository
11+
hugo.exe
12+
hugo.darwin
13+
hugo.linux
14+
15+
# Temporary lock file while building
16+
/.hugo_build.lock
17+

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "themes/hugo-book"]
2+
path = themes/hugo-book
3+
url = https://github.com/alex-shpak/hugo-book

Makefile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
DOCKER_IMAGE := hugomods/hugo:exts
2+
DOCKER_RUN_CMD := docker compose run --rm
3+
4+
all: clean build
5+
6+
up:
7+
docker compose up server
8+
9+
down:
10+
docker compose down --remove-orphans
11+
12+
build:
13+
$(DOCKER_RUN_CMD) server build --minify
14+
15+
clean:
16+
rm -rf ./public
17+
rm -rf ./resources/_gen
18+
19+
shell:
20+
$(DOCKER_RUN_CMD) server /bin/sh

archetypes/default.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
+++
2+
date = '{{ .Date }}'
3+
draft = true
4+
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
5+
+++

content/de/_index.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
bookFlatSection: true
3+
title: "Secure Webhook Token (SWT) Dokumentation"
4+
---
5+
6+
# Secure Webhook Token (SWT) Dokumentation
7+
8+
Diese Dokumentation beschreibt die IETF Draft Spezifikation für Secure Webhook Tokens (SWT) basierend auf [`draft-knauer-secure-webhook-token-00`](https://datatracker.ietf.org/doc/draft-knauer-secure-webhook-token/).
9+
10+
Secure Webhook Token (SWT) ist eine spezialisierte Implementierung von JSON Web Tokens (JWT), die für die sichere Autorisierung von Webhook-Anfragen entwickelt wurde.
11+
12+
## Hauptfunktionen
13+
14+
- **Standardisiert**: Basiert auf bewährten JWT-Standards
15+
- **Sicher**: Integrierte Replay-Schutz und Hash-Validierung
16+
- **Flexibel**: Unterstützt verschiedene Übertragungsmethoden
17+
- **Effizient**: Optimiert für verschiedene Payload-Größen
18+
19+
## Navigation
20+
21+
Diese Dokumentation ist in folgende Bereiche unterteilt:
22+
23+
- **Überblick und Grundlagen**: Einführung in SWT-Konzepte
24+
- **Spezifikation**: Detaillierte technische Spezifikation
25+
- **Implementierung**: Praktische Implementierungsbeispiele
26+
- **Sicherheit**: Sicherheitsrichtlinien und Best Practices

content/de/docs/swt/_index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
weight: 10
3+
bookFlatSection: false
4+
bookCollapseSection: false
5+
title: "SWT"
6+
---
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
---
2+
weight: 30
3+
title: "Fehlerbehandlung"
4+
---
5+
6+
# Fehlerbehandlung
7+
8+
## Häufige Validierungsfehler
9+
10+
| Fehler | Ursache | Lösung |
11+
|--------|---------|--------|
12+
| `Token expired` | Token ist abgelaufen | Neues Token anfordern |
13+
| `Invalid signature` | Falscher Schlüssel oder manipuliertes Token | Schlüssel überprüfen |
14+
| `Hash mismatch` | Payload wurde verändert | Originale Payload verwenden |
15+
| `Missing claims` | Pflicht-Claims fehlen | Token-Struktur korrigieren |
16+
| `Token not yet valid` | nbf-Claim liegt in der Zukunft | Clock-Synchronisation prüfen |
17+
| `Replay attack detected` | JTI bereits verwendet | Neues Token generieren |
18+
19+
## Beispiel-Fehlerbehandlung
20+
21+
```javascript
22+
app.post('/webhook', (req, res) => {
23+
try {
24+
const token = req.headers.authorization?.replace('Bearer ', '');
25+
const validatedToken = validateSWT(token, req.body, SECRET_KEY);
26+
27+
// Webhook verarbeiten
28+
processWebhook(validatedToken.webhook, req.body);
29+
30+
res.status(200).json({ status: 'success' });
31+
} catch (error) {
32+
console.error('Webhook-Validierung fehlgeschlagen:', error.message);
33+
34+
// Spezifische Fehlerbehandlung
35+
if (error.message.includes('expired')) {
36+
return res.status(401).json({
37+
error: 'TOKEN_EXPIRED',
38+
message: 'Token ist abgelaufen'
39+
});
40+
}
41+
42+
if (error.message.includes('signature')) {
43+
return res.status(401).json({
44+
error: 'INVALID_SIGNATURE',
45+
message: 'Token-Signatur ungültig'
46+
});
47+
}
48+
49+
if (error.message.includes('Hash')) {
50+
return res.status(400).json({
51+
error: 'PAYLOAD_MISMATCH',
52+
message: 'Payload wurde verändert'
53+
});
54+
}
55+
56+
// Allgemeiner Fehler
57+
res.status(401).json({
58+
error: 'UNAUTHORIZED',
59+
message: 'Token-Validierung fehlgeschlagen'
60+
});
61+
}
62+
});
63+
```
64+
65+
## Erweiterte Fehlerbehandlung
66+
67+
### Fehlerklassen definieren
68+
69+
```javascript
70+
class SWTError extends Error {
71+
constructor(message, code, statusCode = 401) {
72+
super(message);
73+
this.name = 'SWTError';
74+
this.code = code;
75+
this.statusCode = statusCode;
76+
}
77+
}
78+
79+
class TokenExpiredError extends SWTError {
80+
constructor() {
81+
super('Token ist abgelaufen', 'TOKEN_EXPIRED', 401);
82+
}
83+
}
84+
85+
class InvalidSignatureError extends SWTError {
86+
constructor() {
87+
super('Token-Signatur ungültig', 'INVALID_SIGNATURE', 401);
88+
}
89+
}
90+
91+
class PayloadMismatchError extends SWTError {
92+
constructor() {
93+
super('Payload-Hash stimmt nicht überein', 'PAYLOAD_MISMATCH', 400);
94+
}
95+
}
96+
97+
class ReplayAttackError extends SWTError {
98+
constructor() {
99+
super('Token bereits verwendet', 'REPLAY_ATTACK', 401);
100+
}
101+
}
102+
```
103+
104+
### Verbesserte Validierungsfunktion
105+
106+
```javascript
107+
function validateSWT(token, payload, secret) {
108+
try {
109+
const decoded = jwt.verify(token, secret);
110+
111+
// Pflicht-Claims prüfen
112+
const requiredClaims = ['webhook', 'iss', 'exp', 'nbf', 'iat', 'jti'];
113+
for (const claim of requiredClaims) {
114+
if (!decoded[claim]) {
115+
throw new SWTError(`Fehlender Pflicht-Claim: ${claim}`, 'MISSING_CLAIM', 400);
116+
}
117+
}
118+
119+
// Zeitvalidierung
120+
const now = Math.floor(Date.now() / 1000);
121+
if (decoded.exp <= now) {
122+
throw new TokenExpiredError();
123+
}
124+
if (decoded.nbf > now) {
125+
throw new SWTError('Token noch nicht gültig', 'TOKEN_NOT_YET_VALID', 401);
126+
}
127+
128+
// Payload-Hash validieren
129+
if (payload && decoded.webhook.hash) {
130+
const [algorithm, expectedHash] = decoded.webhook.hash.split(':');
131+
const actualHash = crypto.createHash(algorithm)
132+
.update(JSON.stringify(payload))
133+
.digest('hex');
134+
135+
if (actualHash !== expectedHash) {
136+
throw new PayloadMismatchError();
137+
}
138+
}
139+
140+
return decoded;
141+
} catch (error) {
142+
if (error instanceof SWTError) {
143+
throw error;
144+
}
145+
146+
if (error.name === 'TokenExpiredError') {
147+
throw new TokenExpiredError();
148+
}
149+
150+
if (error.name === 'JsonWebTokenError') {
151+
throw new InvalidSignatureError();
152+
}
153+
154+
throw new SWTError('Unbekannter Validierungsfehler', 'VALIDATION_ERROR', 500);
155+
}
156+
}
157+
```
158+
159+
## Logging und Monitoring
160+
161+
### Strukturiertes Logging
162+
163+
```javascript
164+
const winston = require('winston');
165+
166+
const logger = winston.createLogger({
167+
level: 'info',
168+
format: winston.format.combine(
169+
winston.format.timestamp(),
170+
winston.format.errors({ stack: true }),
171+
winston.format.json()
172+
),
173+
transports: [
174+
new winston.transports.File({ filename: 'webhook-errors.log', level: 'error' }),
175+
new winston.transports.File({ filename: 'webhook-combined.log' })
176+
]
177+
});
178+
179+
function logWebhookEvent(event, details, level = 'info') {
180+
logger.log({
181+
level: level,
182+
message: 'Webhook Event',
183+
event: event,
184+
details: details,
185+
timestamp: new Date().toISOString()
186+
});
187+
}
188+
189+
// Verwendung
190+
try {
191+
const validatedToken = validateSWT(token, req.body, SECRET_KEY);
192+
logWebhookEvent('webhook_validated', {
193+
event: validatedToken.webhook.event,
194+
jti: validatedToken.jti,
195+
issuer: validatedToken.iss
196+
});
197+
} catch (error) {
198+
logWebhookEvent('webhook_validation_failed', {
199+
error: error.message,
200+
code: error.code,
201+
ip: req.ip,
202+
userAgent: req.get('User-Agent')
203+
}, 'error');
204+
}
205+
```
206+
207+
### Metriken und Alerting
208+
209+
```javascript
210+
const prometheus = require('prom-client');
211+
212+
// Metriken definieren
213+
const webhookValidationCounter = new prometheus.Counter({
214+
name: 'webhook_validation_total',
215+
help: 'Total number of webhook validations',
216+
labelNames: ['status', 'error_type']
217+
});
218+
219+
const webhookValidationDuration = new prometheus.Histogram({
220+
name: 'webhook_validation_duration_seconds',
221+
help: 'Duration of webhook validation',
222+
buckets: [0.1, 0.5, 1, 2, 5]
223+
});
224+
225+
// Metriken verwenden
226+
app.post('/webhook', async (req, res) => {
227+
const startTime = Date.now();
228+
229+
try {
230+
const validatedToken = validateSWT(token, req.body, SECRET_KEY);
231+
232+
webhookValidationCounter.inc({ status: 'success', error_type: 'none' });
233+
processWebhook(validatedToken.webhook, req.body);
234+
235+
res.status(200).json({ status: 'success' });
236+
} catch (error) {
237+
webhookValidationCounter.inc({
238+
status: 'error',
239+
error_type: error.code || 'unknown'
240+
});
241+
242+
res.status(error.statusCode || 500).json({
243+
error: error.code || 'UNKNOWN_ERROR',
244+
message: error.message
245+
});
246+
} finally {
247+
const duration = (Date.now() - startTime) / 1000;
248+
webhookValidationDuration.observe(duration);
249+
}
250+
});
251+
```
252+
253+
## Rate Limiting
254+
255+
```javascript
256+
const rateLimit = require('express-rate-limit');
257+
258+
const webhookLimiter = rateLimit({
259+
windowMs: 15 * 60 * 1000, // 15 Minuten
260+
max: 100, // Maximal 100 Requests pro IP
261+
message: {
262+
error: 'RATE_LIMIT_EXCEEDED',
263+
message: 'Zu viele Webhook-Anfragen'
264+
},
265+
standardHeaders: true,
266+
legacyHeaders: false,
267+
skip: (req) => {
268+
// Authentifizierte Requests weniger limitieren
269+
const token = req.headers.authorization?.replace('Bearer ', '');
270+
try {
271+
jwt.verify(token, SECRET_KEY);
272+
return false; // Nicht skippen, aber weniger streng limitieren
273+
} catch {
274+
return false;
275+
}
276+
}
277+
});
278+
279+
app.use('/webhook', webhookLimiter);
280+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
weight: 40
3+
bookFlatSection: false
4+
bookCollapseSection: false
5+
bookToc: false
6+
title: "Implementierungen"
7+
---
8+
9+
# Implementierungen
10+
11+
{{% hint danger %}}
12+
**Contribution wanted!**
13+
14+
Wenn du eine Library für eine andere Sprache kennst oder eine erstellt hast, lass es mich wissen und ich trage sie hier ein.
15+
{{% /hint %}}
16+
17+
Hier ist eine Liste mit Implementierungen in verschiedenen Programmiersprachen.
18+
19+
## Go
20+
21+
- [SecureWebhookToken (SWT)](https://github.com/securewebhooktoken/swt)
22+
23+
## JS
24+
25+
- ???
26+
27+
## Python
28+
29+
- ???

0 commit comments

Comments
 (0)