Why Webhook Signature Verification Is Essential
When using the LINE Messaging API for Bots or Mini Apps, LINE sends events via webhooks. Since webhook endpoints are public URLs, they can receive forged requests from third parties.
Risks without signature verification:
- Spoofing attacks — attackers impersonating LINE with fake events
- Data tampering — request contents modified in transit
- Unauthorized actions — fake message events triggering unintended bot behavior
How Signature Verification Works
LINE includes an X-Line-Signature header with every webhook request. This header contains a Base64-encoded HMAC-SHA256 digest of the request body, using your channel secret as the key.
Correct Implementation
import crypto from 'crypto';
function validateSignature(body, signature, channelSecret) {
const hash = crypto
.createHmac('SHA256', channelSecret)
.update(body)
.digest('base64');
return crypto.timingSafeEqual(
Buffer.from(hash),
Buffer.from(signature)
);
}
// Express.js usage
app.post('/webhook', express.raw({ type: '*/*' }), (req, res) => {
const signature = req.headers['x-line-signature'];
if (!validateSignature(req.body, signature, CHANNEL_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Signature valid — process events
handleEvents(JSON.parse(req.body));
res.status(200).send('OK');
});
Common Mistakes
1. Verifying after parsing the body
// Wrong — parsed body produces incorrect hash
app.post('/webhook', express.json(), (req, res) => {
validateSignature(JSON.stringify(req.body), ...); // NG
});
You must verify against the raw request body (Buffer).
2. Using simple string comparison
// Wrong — vulnerable to timing attacks
if (hash === signature) { ... }
Use crypto.timingSafeEqual for constant-time comparison.
3. Hardcoding the channel secret
Manage it via environment variables — never include it in source code.
WebMori's LINE API Audit
WebMori's LINE API audit automatically checks:
- X-Line-Signature verification implementation
- Channel access token management
- LIFF URL HTTPS configuration
- Rate limit (429 response) handling
- Secure userId storage
If you're running a LINE Bot, try our free audit today.