Skip to content

Commit

Permalink
chore(docs): adding programming languages tabs, more examples to hmac…
Browse files Browse the repository at this point in the history
… signature verification (#2648)
  • Loading branch information
alonp99 authored Aug 27, 2024
1 parent b53e5f9 commit 06ab85f
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 4 deletions.
7 changes: 7 additions & 0 deletions websites/docs/.astro/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,13 @@ declare module 'astro:content' {
collection: 'docs';
data: InferEntrySchema<'docs'>;
} & { render(): Render['.md'] };
'en/learn/webhooks_security.mdx': {
id: 'en/learn/webhooks_security.mdx';
slug: 'en/learn/webhooks_security';
body: string;
collection: 'docs';
data: InferEntrySchema<'docs'>;
} & { render(): Render['.mdx'] };
'en/learn/workflow_builder_and_rule_engine_overview.md': {
id: 'en/learn/workflow_builder_and_rule_engine_overview.md';
slug: 'en/learn/workflow_builder_and_rule_engine_overview';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
import {Tabs, TabItem} from '@astrojs/starlight/components';
import CodeBlock from "../CodeBlock/CodeBlock.astro";
export interface Props {
code: string | {
javascript?: string;
typescript?: string;
python?: string;
php?: string;
java?: string;
};
}
const {code} = Astro.props;
const languages = typeof code === 'string'
? [{ label: 'Code', code }]
: [
{ label: 'JavaScript', code: code.javascript },
{ label: 'TypeScript', code: code.typescript },
{ label: 'Python', code: code.python },
{ label: 'PHP', code: code.php },
{ label: 'Java', code: code.java }
].filter(lang => lang.code !== undefined);
---

<Tabs>
{languages.map(lang => (
<TabItem label={lang.label}>
<CodeBlock lang={lang.label.toLowerCase()} code={lang.code}/>
</TabItem>
))}
</Tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: How to use webhooks
description: A guide on setting up and handling webhooks to receive real-time notifications from Ballerine's system events.
---

import CodeBlock from '../../../../components/CodeBlock/CodeBlock.astro';

**Ballerine supports two types of webhooks: system webhooks and custom webhooks.
These webhooks allow you to integrate external systems and automate actions based on specific events in your workflows.**

Expand Down
76 changes: 72 additions & 4 deletions websites/docs/src/content/docs/en/learn/webhooks_security.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ title: Webhook Security
description: Ensuring the security of webhooks from Ballerine's system.
---

import ProgrammingLanguagesTabs from '../../../../components/ProgrammingLanguagesTabs/ProgrammingLanguagesTabs.astro';


## Webhook Security

Security is a critical aspect of handling webhooks to ensure that your application processes legitimate requests and that sensitive data remains protected. Ballerine takes webhook security seriously and provides mechanisms to verify the authenticity of webhook requests. This section explains how to verify webhooks from Ballerine, best practices for securing your webhook endpoints, and additional security measures you can implement.
Expand All @@ -24,8 +27,8 @@ To verify the authenticity of the webhook, Ballerine signs the entire payload of

Here is a complete example demonstrating how to authenticate webhooks from Ballerine:

```javascript
const express = require('express');
<ProgrammingLanguagesTabs code={{
javascript: `const express = require('express');
const crypto = require('crypto');
const app = express();
const port = 3000;
Expand Down Expand Up @@ -57,9 +60,74 @@ function verifyPayload(payload, secret, signature) {
}
app.listen(port, () => {
console.log(`Webhook listener running on port ${port}`);
console.log(\`Webhook listener running on port \${port}\`);
});`,
python: `from flask import Flask, request, jsonify
import hmac
import hashlib
import json
app = Flask(__name__)
ballerine_secret = 'your_secret_key'
@app.route('/webhook', methods=['POST'])
def webhook():
payload = request.json
signature = request.headers.get('x-hmac-signature')
if verify_payload(payload, ballerine_secret, signature):
print('Webhook verified successfully')
# Process the webhook payload
return 'Webhook received', 200
else:
print('Invalid webhook signature')
return 'Invalid signature', 401
def verify_payload(payload, secret, signature):
generated_signature = hmac.new(
secret.encode('utf-8'),
json.dumps(payload).encode('utf-8'),
hashlib.sha256
).hexdigest()
return generated_signature == signature
if __name__ == '__main__':
app.run(port=3000)`,
php: `<?php
require 'vendor/autoload.php';
use Slim\Factory\AppFactory;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
$app = AppFactory::create();
$ballerineSecret = 'your_secret_key';
$app->post('/webhook', function (Request $request, Response $response) use ($ballerineSecret) {
$payload = json_decode($request->getBody()->getContents(), true);
$signature = $request->getHeaderLine('x-hmac-signature');
if (verifyPayload($payload, $ballerineSecret, $signature)) {
error_log('Webhook verified successfully');
// Process the webhook payload
$response->getBody()->write('Webhook received');
return $response->withStatus(200);
} else {
error_log('Invalid webhook signature');
$response->getBody()->write('Invalid signature');
return $response->withStatus(401);
}
});
```
function verifyPayload($payload, $secret, $signature) {
$generatedSignature = hash_hmac('sha256', json_encode($payload), $secret);
return hash_equals($generatedSignature, $signature);
}
$app->run();`,
}} />

### Best Practices for Webhook Security

Expand Down

0 comments on commit 06ab85f

Please sign in to comment.