Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ deprecated: false
ai_summary: "Documentation for kinde.secureFetch binding that enables encrypted HTTP requests for sensitive data transmission with automatic encryption of POST body content."
---

The `kinde.secureFetch` binding allows you to make POST requests to external APIs where the payload is encrypted with the [workflow encryption key](/workflows/manage-workflows/workflow-encryption-key/) you have previously set up in Kinde.
The `kinde.secureFetch` binding allows you to make POST requests to external APIs where the payload is encrypted with the [workflow encryption key](/workflows/manage-workflows/encrypt-decrypt-workflows/) you have previously set up in Kinde.

## Available in workflows

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
---
page_id: 961c2bf6-2683-4339-b42a-928e328ce74b
title: Workflow encryption key
sidebar:
order: 3
relatedArticles:
- d672fca7-6c6a-49f8-85c9-6e86ce99f440
- 8554d648-fc2f-4ef9-aaa9-4f27b3c05205
description: Learn about workflow encryption keys used to secure sensitive data transmission in secure fetch operations and other encrypted workflow communications in Kinde workflows.
topics:
- "workflows"
- "manage-workflows"
- "security"
sdk: null
languages:
- "TypeScript"
- "JavaScript"
- "C#"
- ".NET"
audience:
- "developers"
- "admins"
complexity: "intermediate"
keywords:
- "encryption key"
- "security"
- "secure fetch"
- "sensitive data"
- "encryption"
updated: "2025-09-29"
featured: false
deprecated: false
ai_summary: "Documentation for workflow encryption keys used to secure sensitive data transmission in secure fetch operations and other encrypted workflow communications."
---

You can generate unique encryption keys to be used to make secure API calls within your workflows.

Encryption keys protect sensitive data and should be updated regularly for continued protection.

Keys are per-workflow, so you can have different keys for different workflows. You can also have multiple keys for a single workflow, but only one key can be active at a time.

## How encryption keys work

When an POST request is made using the [kinde.secureFetch binding](/workflows/bindings/secure-fetch-binding/), the body is automatically encrypted with the active encryption key for the workflow. Use the same encryption key in your own code to decrypt the payload on arrival. This ensures secure transfer of the data.

## Add an encryption key to a workflow

1. Go to **Workflows** and select a workflow.
2. Select **Encryption keys** in the menu.
3. Select **Add encryption key**. A dialog appears, enabling you to copy the key. You need to copy it immediately, as it cannot be viewed again.
4. After you copy the key, select **Close**. If this is the first key you have added, it will automatically be made **active**.
5. Add the key to your code, to decrypt data sent from Kinde.

## Decrypt workflow‑encrypted payloads

Decrypting methods depend on your systems and framework. Here's how to decrypt if you are using .NET.

Situation: You use `kinde.secureFetch` and the payload is encrypted with your workflow’s active encryption key using AES-GCM, then encoded in Base64.

Method: Decrypt the request body in your .NET API:

1. In Base64, decode the incoming payload.
2. In AES-GCM, decrypt the decoded data using your workflow’s active encryption key (the one you created in the Kinde dashboard).
3. In .NET, for example, use the `System.Security.Cryptography.AesGcm` class for decryption.

The payload structure includes the nonce (IV), tag, and ciphertext. These will be provided in the encrypted request payload, so your code should parse them out before decrypting.

```csharp
using System;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

public class WorkflowPayloadDecryptor
{
private readonly byte[] _encryptionKey;

public WorkflowPayloadDecryptor(string base64EncryptionKey)
{
_encryptionKey = Convert.FromBase64String(base64EncryptionKey);
}

public string DecryptPayload(string encryptedPayload)
{
try
{
// Step 1: Base64 decode the incoming payload
byte[] encryptedData = Convert.FromBase64String(encryptedPayload);

// Step 2: Parse the payload structure
// The payload contains: nonce (12 bytes) + tag (16 bytes) + ciphertext
const int nonceLength = 12;
const int tagLength = 16;

if (encryptedData.Length < nonceLength + tagLength)
{
throw new ArgumentException("Invalid encrypted payload structure");
}

// Extract components
byte[] nonce = new byte[nonceLength];
byte[] tag = new byte[tagLength];
byte[] ciphertext = new byte[encryptedData.Length - nonceLength - tagLength];

Array.Copy(encryptedData, 0, nonce, 0, nonceLength);
Array.Copy(encryptedData, nonceLength, tag, 0, tagLength);
Array.Copy(encryptedData, nonceLength + tagLength, ciphertext, 0, ciphertext.Length);

// Step 3: Decrypt using AES-GCM
using (var aesGcm = new AesGcm(_encryptionKey))
{
byte[] decryptedBytes = new byte[ciphertext.Length];
aesGcm.Decrypt(nonce, ciphertext, tag, decryptedBytes);

// Convert decrypted bytes to string
return Encoding.UTF8.GetString(decryptedBytes);
}
}
catch (Exception ex)
{
throw new InvalidOperationException("Failed to decrypt workflow payload", ex);
}
}
}

// Example usage in an ASP.NET Core controller
[ApiController]
[Route("api/[controller]")]
public class WorkflowController : ControllerBase
{
private readonly WorkflowPayloadDecryptor _decryptor;

public WorkflowController(IConfiguration configuration)
{
// Get the encryption key from configuration
string encryptionKey = configuration["KindeWorkflowEncryptionKey"];
_decryptor = new WorkflowPayloadDecryptor(encryptionKey);
}

[HttpPost("webhook")]
public async Task<IActionResult> HandleWorkflowWebhook()
{
try
{
// Read the encrypted payload from the request body
using var reader = new StreamReader(Request.Body);
string encryptedPayload = await reader.ReadToEndAsync();

// Decrypt the payload
string decryptedJson = _decryptor.DecryptPayload(encryptedPayload);

// Parse the decrypted JSON
var workflowData = JsonSerializer.Deserialize<WorkflowData>(decryptedJson);

// Process the decrypted data
// ... your business logic here ...

return Ok(new { message = "Workflow payload processed successfully" });
}
catch (Exception ex)
{
return BadRequest(new { error = "Failed to process workflow payload", details = ex.Message });
}
}
}

// Example data model for the decrypted payload
public class WorkflowData
{
public string UserId { get; set; }
public string EventType { get; set; }
public Dictionary<string, object> Data { get; set; }
}
```
Comment on lines +69 to +174
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add the missing using directives so the sample compiles.

The C# snippet references StreamReader, ControllerBase, IConfiguration, Task<IActionResult>, and Dictionary<string, object>, but the code block only imports core namespaces. Without the matching using statements (System.IO, System.Collections.Generic, System.Threading.Tasks, Microsoft.AspNetCore.Mvc, Microsoft.Extensions.Configuration), readers copying the sample will hit compile errors. Please prepend the snippet with the full set of namespaces (or annotate them inline) so the example builds cleanly.

🤖 Prompt for AI Agents
In src/content/docs/workflows/manage-workflows/encrypt-decrypt-workflows.mdx
around lines 67 to 172, the C# sample is missing required using directives which
cause compile errors for StreamReader, Dictionary, Task<IActionResult>,
ControllerBase and IConfiguration; prepend the file’s code block with the
following usings: System.IO, System.Collections.Generic, System.Threading.Tasks,
Microsoft.AspNetCore.Mvc, and Microsoft.Extensions.Configuration (keeping the
existing System, System.Security.Cryptography, System.Text, and System.Text.Json
lines) so the sample compiles cleanly.


### Configuration

Add your workflow encryption key to your `appsettings.json`:

```json
{
"KindeWorkflowEncryptionKey": "your-base64-encoded-encryption-key-here"
}
```

Or set it as an environment variable:

```bash
KindeWorkflowEncryptionKey=your-base64-encoded-encryption-key-here
```

## Update an encryption key

1. Go to **Workflows** and select a workflow.
2. Select **Encryption keys** in the menu.
3. Select **Add encryption key**. A dialog opens with information about adding the key.
4. Select **Add**. A dialog appears showing the key value.
5. Copy the key value and store it somewhere you can access again.
6. Select **Close**.
7. When you are ready to update the key in your code, select the three dots menu on the new key, then select **Activate**. A dialog opens, confirming the action.
8. Select **Activate encryption key**. This makes the new key active and deactivates the previously active key.
9. Add the new key value to your code, to continue decrypting data sent from Kinde.

## Deactivate/activate an encryption key

You can change the active status of any key. Remember to update your code to use the active key.

1. Go to **Workflows** and select a workflow.
2. Select **Encryption keys** in the menu.
3. To deactivate an active key:
1. Select the three dots menu on the active key.
2. Select **Deactivate**. A confirmation window opens.
3. Follow the prompts and select **Deactivate encryption key.**
4. To activate a deactivated key:
1. Select the three dots menu on the inactive key. An inactive key shows no status.
2. Select **Activate**. A confirmation window opens.
3. Follow the prompts and select **Activate encryption key**. This makes the new key active and deactivates any previously active key.

## Delete used or unwanted encryption keys

Deleting used keys is good security hygiene. But deleting an active key can also break your code. Only delete inactive keys.

1. Go to **Workflows** and select a workflow.
2. Select **Encryption keys** in the menu.
3. Next to an inactive key, select the three dots menu.
4. Select **Delete key**. A confirmation window opens.
5. Follow the prompts and select **Delete encryption key**.

This file was deleted.