fix: Gitea-Webhook akzeptiert HMAC-Signatur (X-Gitea-Signature)
Gitea sendet das Webhook-Secret als HMAC-SHA256-Signatur des Bodys, nicht als Klartext-Header. Bisher liefen alle per Secret konfigurierten Repo-Hooks auf 401 - Push-Deploys funktionierten nur ueber ?token= in der URL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,8 @@ assertServerConfig()
|
|||||||
const app = express()
|
const app = express()
|
||||||
app.set('trust proxy', 1)
|
app.set('trust proxy', 1)
|
||||||
app.use(sessionMiddleware())
|
app.use(sessionMiddleware())
|
||||||
app.use(express.json({ limit: '2mb' }))
|
// rawBody wird fuer die HMAC-Verifikation des Gitea-Webhooks benoetigt
|
||||||
|
app.use(express.json({ limit: '2mb', verify: (req, _res, buf) => { req.rawBody = buf } }))
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
const origin = req.get('Origin')
|
const origin = req.get('Origin')
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import crypto from 'node:crypto'
|
||||||
import { Router } from 'express'
|
import { Router } from 'express'
|
||||||
import { config } from '../../config.js'
|
import { config } from '../../config.js'
|
||||||
import { upsertWebsiteProjectByRepo } from '../../services/appwriteAdmin.js'
|
import { upsertWebsiteProjectByRepo } from '../../services/appwriteAdmin.js'
|
||||||
@@ -15,8 +16,21 @@ function verifyWebhookToken(req) {
|
|||||||
const token = config.gitea.webhookToken
|
const token = config.gitea.webhookToken
|
||||||
if (!token) return false
|
if (!token) return false
|
||||||
const queryToken = req.query.token
|
const queryToken = req.query.token
|
||||||
const headerToken = req.get('X-Gitea-Token') || req.get('X-Gogs-Signature')
|
const headerToken = req.get('X-Gitea-Token')
|
||||||
return queryToken === token || headerToken === token
|
if (queryToken === token || headerToken === token) return true
|
||||||
|
|
||||||
|
// Gitea sendet das Webhook-Secret nicht im Klartext, sondern als
|
||||||
|
// HMAC-SHA256-Signatur des Request-Bodys (X-Gitea-Signature).
|
||||||
|
const signature = req.get('X-Gitea-Signature') || req.get('X-Gogs-Signature')
|
||||||
|
if (signature && req.rawBody) {
|
||||||
|
const expected = crypto.createHmac('sha256', token).update(req.rawBody).digest('hex')
|
||||||
|
try {
|
||||||
|
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
router.post('/gitea', async (req, res) => {
|
router.post('/gitea', async (req, res) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user