> ## Documentation Index
> Fetch the complete documentation index at: https://docs.riseworks.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Security and Verification

> How to verify webhook authenticity and secure your endpoints

Webhook security is critical for protecting your application from malicious attacks and ensuring data integrity. This guide covers everything you need to implement robust security for your Rise webhook endpoints.

## Why webhook security matters

Without proper security measures, attackers could:

<CardGroup cols={2}>
  <Card title="Send fake events" icon="triangle-exclamation">
    Trigger unauthorized actions in your system with fabricated webhook events
  </Card>

  <Card title="Replay old events" icon="rotate-left">
    Duplicate transactions or operations by resending legitimate webhook data
  </Card>

  <Card title="Intercept webhook data" icon="eye">
    Access sensitive payment information transmitted over insecure connections
  </Card>

  <Card title="Overwhelm servers" icon="server">
    Launch denial-of-service attacks against your webhook endpoints
  </Card>
</CardGroup>

## Security architecture overview

Rise webhooks include multiple layers of security to protect your integration:

<Steps>
  <Step title="HTTPS encryption">
    All data encrypted in transit between Rise and your endpoint
  </Step>

  <Step title="Signature verification">
    Cryptographic proof that requests actually came from Rise
  </Step>

  <Step title="Timestamp validation">
    Protection against replay attacks using time-based verification
  </Step>

  <Step title="Secret management">
    Secure storage and handling of webhook secrets
  </Step>
</Steps>

## Signature verification

Every Rise webhook includes a cryptographic signature that proves the request came from Rise.

<Info>
  **SDK Installation**: Install the Rise SDK to get secure, type-safe webhook verification: `npm install @riseworks/riseworks-sdk` (or `yarn add @riseworks/riseworks-sdk` / `pnpm add @riseworks/riseworks-sdk`)
</Info>

### How signatures work

1. **Rise generates signature** using your webhook secret and event data
2. **Signature included in headers** with timestamp information
3. **Your endpoint verifies** the signature matches expected value
4. **Process event** only if signature is valid

### Signature header format

Rise includes the signature in the `X-Rise-Signature` header:

```
X-Rise-Signature: t=1640995200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
```

* `t=` - Timestamp when the signature was generated
* `v1=` - The signature hash using HMAC-SHA256

### Implementing signature verification

The Rise SDK provides a secure, type-safe way to verify webhook signatures. Here's how to use it:

<CodeGroup>
  ```javascript Node.js theme={null}
  import { WebhookValidator } from '@riseworks/riseworks-sdk';

  // Create validator instance with your webhook secret
  const validator = new WebhookValidator({
    secret: process.env.RISE_WEBHOOK_SECRET,
    tolerance: 600 // 10 minutes (default)
  });

  // Express.js middleware example
  app.use('/rise-webhooks', express.raw({ type: 'application/json' }));

  app.post('/rise-webhooks', async (req, res) => {
    const signature = req.headers['x-rise-signature'];
    
    try {
      // Verify signature and get validated event (uses default tolerance)
      const event = validator.validateEvent(req.body, signature);
      
      // For high-security scenarios, you can override tolerance:
      // const event = validator.validateEvent(req.body, signature, { tolerance: 60 });
      
      // Event is now verified and typed - process it
      handleWebhookEvent(event);
      
      res.status(200).json({ received: true });
    } catch (error) {
      console.error('Webhook verification failed:', error.message);
      res.status(400).send('Invalid signature');
    }
  });
  ```

  ```python Python theme={null}
  from riseworks import WebhookValidator

  # Create validator instance
  validator = WebhookValidator(
      secret=os.environ.get('RISE_WEBHOOK_SECRET'),
      tolerance=600  # 10 minutes
  )

  # Flask example
  @app.route('/rise-webhooks', methods=['POST'])
  def handle_webhook():
      signature = request.headers.get('X-Rise-Signature')
      
      try:
          # Verify signature and get validated event
          event = validator.validateEvent(request.get_data(), signature)
          
          # Event is now verified and typed - process it
          handle_webhook_event(event)
          
          return jsonify({'received': True}), 200
      except Exception as e:
          print(f'Webhook verification failed: {e}')
          return 'Invalid signature', 400
  ```
</CodeGroup>

<Info>
  **SDK Benefits**: The Rise SDK handles all signature verification, timestamp validation, and type safety automatically. It also provides TypeScript types for all webhook events.
</Info>

## HTTPS recommendations

HTTPS is recommended for production webhook endpoints to protect data in transit, though Rise supports both HTTP and HTTPS endpoints.

<Info>
  Rise webhooks work with both HTTP and HTTPS endpoints. For production environments handling sensitive financial data, HTTPS is recommended for security. HTTP endpoints are perfectly suitable for development, testing, and localhost environments.
</Info>

### Why HTTPS is recommended

<CardGroup cols={2}>
  <Card title="Data encryption" icon="lock">
    Prevents interception of sensitive payment data during transmission
  </Card>

  <Card title="Authentication" icon="award">
    Ensures you're communicating with Rise's legitimate servers
  </Card>

  <Card title="Integrity" icon="shield">
    Prevents tampering with webhook data during transmission
  </Card>

  <Card title="Compliance" icon="scale-balanced">
    Required for PCI DSS and financial data protection standards
  </Card>
</CardGroup>

For production environments, HTTPS with a valid SSL certificate is recommended. For development and testing, HTTP endpoints (including localhost and ngrok) work perfectly fine. Use the Rise app's test feature to verify your endpoint is properly configured.

## Preventing replay attacks

Replay attacks occur when an attacker intercepts a valid webhook and sends it again later.

### How replay protection works

1. **Rise includes timestamp** in every webhook signature
2. **Your endpoint checks timestamp** against current time
3. **Reject old requests** outside tolerance window
4. **Log suspicious activity** for monitoring

### Timestamp validation with SDK

The Rise SDK automatically handles timestamp validation with configurable tolerance. You can set a default tolerance in the constructor and override it per validation call:

```javascript theme={null}
import { WebhookValidator } from '@riseworks/riseworks-sdk';

// Create validator with default tolerance (10 minutes)
const validator = new WebhookValidator({
  secret: process.env.RISE_WEBHOOK_SECRET,
  tolerance: 600 // 10 minutes (default)
});

// Use default tolerance
const event = validator.validateEvent(req.body, signature);

// Override tolerance for high-security scenarios
const strictEvent = validator.validateEvent(req.body, signature, { 
  tolerance: 60 // 1 minute for high security
});

// Override tolerance for systems with clock sync issues
const lenientEvent = validator.validateEvent(req.body, signature, { 
  tolerance: 900 // 15 minutes for clock sync issues
});
```

### Choosing tolerance windows

<AccordionGroup>
  <Accordion title="10 minutes (600 seconds)" icon="clock">
    **Recommended for most applications**

    Provides good security while allowing for reasonable network delays and clock differences between servers.
  </Accordion>

  <Accordion title="1 minute (60 seconds)" icon="stopwatch">
    **High security environments**

    Maximum security but may cause issues if your server has clock synchronization problems or high network latency.
  </Accordion>

  <Accordion title="15 minutes (900 seconds)" icon="hourglass">
    **Systems with clock issues**

    For systems with known clock synchronization issues, but reduces replay attack protection.
  </Accordion>
</AccordionGroup>

<Warning>
  Don't set tolerance to 0 seconds - this disables replay protection entirely and may cause legitimate webhooks to fail.
</Warning>

## Secret management

Webhook secrets are critical security credentials that require careful handling.

### Secret storage best practices

<CardGroup cols={2}>
  <Card title="Environment variables" icon="terminal">
    Never hardcode secrets in source code - use environment variables instead
  </Card>

  <Card title="Secure vaults" icon="vault">
    Use AWS Secrets Manager, HashiCorp Vault, or similar secure storage systems
  </Card>

  <Card title="Encryption at rest" icon="hard-drive">
    Encrypt secret storage and limit access to authorized personnel only
  </Card>

  <Card title="Access control" icon="users">
    Implement role-based access control for viewing and modifying secrets
  </Card>
</CardGroup>

## Common security pitfalls

Avoid these common webhook security mistakes:

<Tabs>
  <Tab title="Don't do this">
    ```javascript theme={null}
    // WRONG: Skipping signature verification
    app.post('/webhooks', (req, res) => {
      // Processing without verification - DANGEROUS!
      handleEvent(req.body);
      res.status(200).send('OK');
    });

    // WRONG: Using HTTP in production
    const webhookUrl = 'http://mysite.com/webhooks'; // Insecure!

    // WRONG: Hardcoded secrets
    const secret = 'whsec_abc123'; // Never do this!

    // WRONG: No timestamp validation
    function verifySignature(payload, signature, secret) {
      // Missing timestamp check allows replays
      return crypto.createHmac('sha256', secret)
        .update(JSON.stringify(payload))
        .digest('hex') === signature;
    }
    ```
  </Tab>

  <Tab title="Do this instead">
    ```javascript theme={null}
    // CORRECT: Using Rise SDK for security
    import { WebhookValidator } from '@riseworks/riseworks-sdk';

    const validator = new WebhookValidator({
      secret: process.env.RISE_WEBHOOK_SECRET,
      tolerance: 600
    });

    app.post('/webhooks', async (req, res) => {
      try {
        // SDK handles all verification automatically (uses default tolerance)
        const event = validator.validateEvent(req.body, req.headers['x-rise-signature']);
        
        // For high-security scenarios, override tolerance per request:
        // const event = validator.validateEvent(req.body, req.headers['x-rise-signature'], { tolerance: 60 });
        
        // Process only verified events with full type safety
        handleEvent(event);
        res.status(200).json({ received: true });
      } catch (error) {
        res.status(400).send('Verification failed');
      }
    });

    // CORRECT: HTTPS endpoint
    const webhookUrl = 'https://mysite.com/webhooks';

    // CORRECT: Environment-based secrets
    const secret = process.env.RISE_WEBHOOK_SECRET;
    ```
  </Tab>
</Tabs>

## Testing your security implementation

Use the Rise app's test webhook feature to verify your security implementation:

<Steps>
  <Step title="Send valid test events">
    Confirm your endpoint properly processes legitimate webhook events
  </Step>

  <Step title="Test with invalid signatures">
    Verify your endpoint correctly rejects webhooks with bad signatures
  </Step>

  <Step title="Monitor delivery results">
    Check the delivery history for any security-related errors or failures
  </Step>
</Steps>

## Security checklist

Before deploying to production, verify your implementation:

<AccordionGroup>
  <Accordion title="Signature verification" icon="pen">
    * Webhook signature is verified for every request
    * Invalid signatures are rejected with 400 status
    * Secret is stored securely (not hardcoded)
    * HMAC comparison uses constant-time comparison
  </Accordion>

  <Accordion title="Timestamp validation" icon="clock">
    * Timestamp is checked against current time
    * Appropriate tolerance window is configured
    * Future timestamps are rejected
    * Replay attacks are prevented
  </Accordion>

  <Accordion title="Transport security" icon="lock">
    * HTTPS is recommended for production
    * Valid SSL certificate is installed
    * HTTP redirects to HTTPS (if applicable)
    * Strong TLS configuration
  </Accordion>

  <Accordion title="Error handling" icon="triangle-exclamation">
    * Security errors are logged appropriately
    * Sensitive data is not leaked in error messages
    * Rate limiting is implemented if needed
    * Monitoring alerts are configured
  </Accordion>
</AccordionGroup>

## What's next?

Now that you've secured your webhook endpoints:

<CardGroup cols={2}>
  <Card title="Webhook Management" icon="gear" href="/webhooks/implementation/management">
    Learn how to create, update, and manage your webhook endpoints
  </Card>

  <Card title="Event Types" icon="list" href="/webhooks/implementation/event-types">
    Explore all available events and their data structures
  </Card>

  <Card title="Testing Tools" icon="flask" href="/webhooks/implementation/testing">
    Testing your webhooks locally and troubleshooting common issues
  </Card>

  <Card title="Monitoring" icon="chart-line" href="/webhooks/operations/monitoring">
    Track security metrics and delivery performance
  </Card>
</CardGroup>

<Tip>
  **Security reminder**: Webhook security is not optional. Always implement signature verification and consider HTTPS for production. The few extra lines of code can prevent serious security breaches.
</Tip>
