Authentication and security

A short guide on how Optum handles webhook authentication and how to secure your webhooks.

Once your server is configured to receive payloads from Optum Connections, it will listen for any events sent to your configured endpoint. To ensure that your server only processes webhook deliveries from Optum Connections and that the payloads have not been tampered with, you should validate the webhook signature before processing. This helps avoid spending server resources on unauthorized deliveries and mitigates the risk of man-in-the-middle attacks.

To validate webhook deliveries, follow these steps:

Steps to secure webhooks

1. Create a secret key

When setting up a webhook, Optum Connections requires a secret key for HMAC encryption. This secret key is used to generate a signature for each event payload.

  • Generate a secret key: Choose a random, high-entropy string to use as the secret key.
  • Add the secret key during setup: When creating or configuring your webhook in Optum Connections' dashboard, specify your secret key as part of the webhook’s configuration. See Subscribing to events on how to configure your webhook.

2. Securely store the secret key

After creating a secret key, store it securely on your server to access when verifying webhook signatures. Never hardcode the secret key in your application or expose it publicly. For best practices on securely storing authentication credentials, see MDN's security guidelines.


3. Validating incoming webhook deliveries

Optum Connections uses the secret key to create an HMAC signature for each payload, sending the signature in the X-Optum-Webhook-Callback-Hmac-Signature header of each webhook request. To verify the authenticity of a webhook payload:

  1. Extract the signature: Retrieve the X-Optum-Webhook-Callback-Hmac-Signature header from the webhook request.
  2. Compute the HMAC hash: Using the HMAC-SHA256 algorithm, generate a hash of the payload with your secret key.
  3. Compare the hashes: Compare the computed hash to the X-Optum-Webhook-Callback-Hmac-Signature. If they match, the payload is verified.

Implementation examples

Here's how to verify the webhook signature in different languages:

import crypto from 'crypto';
import { Request, Response } from 'express';

function verifyOptumWebhookSignature(req: Request, secretKey: string): boolean {
  const signature = req.headers['x-optum-webhook-callback-hmac-signature'] as string;
  const payload = JSON.stringify(req.body);

  // Compute the hash of the payload using HMAC-SHA256 and your secret key
  const computedHash = crypto.createHmac('sha256', secretKey).update(payload).digest('hex');
  
  // Use a constant-time comparison method to prevent timing attacks
  return crypto.timingSafeEqual(Buffer.from(computedHash), Buffer.from(signature));
}

// In your webhook endpoint handler
app.post('/optum/webhook', (req: Request, res: Response) => {
  const secretKey = process.env.OPTUM_SECRET_KEY as string;

  if (!verifyOptumWebhookSignature(req, secretKey)) {
    console.error('Signature verification failed');
    return res.status(400).send('Invalid signature');
  }

  // Process the webhook event here
  res.status(200).end();
});

Important considerations for validation

  • HMAC hash: Optum Connections uses HMAC-SHA256 to compute the hash signature.
  • Character encoding: Ensure that the payload is handled as UTF-8 if your server or language specifies a character encoding, as payloads may contain Unicode characters.
  • Constant-time comparison: Use a constant-time comparison method, like crypto.timingSafeEqual, to mitigate timing attacks. Avoid using == for comparing strings.

Testing your webhook signature validation

To confirm your implementation, test your signature validation with known values. You can use a sample secret and payload to check if your computed signature matches Optum Connections' signature format.

Example:

  • Secret: "YourSecretKey"
  • Payload: {"event":"sample_event"}
  • Expected signature: [Provide a sample signature here once calculated]

This verification process ensures that your application only processes authorized events from Optum Connections and secures your webhook endpoint against potential tampering.


Handshake protocol

When a new subscription is added, Optum Connections validates the endpoint URL through a handshake protocol. This ensures that the endpoint is valid and ready to receive event data.

Handshake Process

ValidationrRequest: Optum Connections will make a request to the endpoint URL using the HTTP OPTIONS method.
Request headers: The request will include the following header:

  • "WebHook-Request-Origin": applicationBaseUrl (this is added to all requests)

User Requirements

To successfully complete the handshake, your endpoint must:

  1. Implement the OPTIONS verb: The endpoint should handle HTTP OPTIONS requests.
  2. Respond with status 200: The endpoint must respond with a 200 status code.
  3. Include required response headers:
    • Allow: POST
    • "WebHook-Allowed-Origin": applicationBaseUrl

Example

Request from Optum Connections

OPTIONS /your-endpoint-url
Headers:
  "WebHook-Request-Origin": applicationBaseUrl
import axios from 'axios';

const applicationBaseUrl = 'https://optum.com';
const endpointUrl = 'https://your-endpoint-url';

axios.options(endpointUrl, {
  headers: {
    'WebHook-Request-Origin': applicationBaseUrl
  }
})
.then(response => {
  console.log('Handshake request sent successfully');
})
.catch(error => {
  console.error('Error during handshake request:', error);
});

Response from user's endpoint:

Status: 200 OK
Headers:
  Allow: POST
  "WebHook-Allowed-Origin": applicationBaseUrl
import express from 'express';

const app = express();
const applicationBaseUrl = 'https://optum.com';

app.options('/your-endpoint-url', (req, res) => {
  res.setHeader('Allow', 'POST');
  res.setHeader('WebHook-Allowed-Origin', applicationBaseUrl);
  res.sendStatus(200);
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

This handshake protocol ensures that the endpoint is correctly configured to receive event data securely.


What’s Next