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

# Secure mode

<View title="Developer" />

<View title="Federal docs" />

<View title="EU docs" />

This topic explains how to use the secure mode feature to safely evaluate feature flags in a web browser.

## About secure mode

Secure mode ensures that customers' feature flag evaluations are kept private in web browser environments, and that one end user cannot inspect the variations for another end user. On an insecure device, a malicious end user could use a context or user key to identify what flag values another end user receives by analyzing the results of multiple flag evaluations. Secure mode prevents you from doing an evaluation for a context or user key that hasn't been signed on the backend.

Secure mode is available for communication between the following JavaScript-based SDKs and LaunchDarkly:

* Electron
* JavaScript
* Node.js (client-side)
* React Web

Secure mode is not necessary for server-side SDKs.

### How secure mode works

Secure mode works when you configure your JavaScript-based SDK to include a server-generated HMAC SHA256 hash of your context key or user key. This hash is signed with the SDK key for your environment. Enabling secure mode means that every request coming from a client-side JavaScript-based SDK requires the secure mode hash to evaluate flag variations. You can pass this to your front-end code with the mechanism of your choice, such as bootstrapping or as a template variable.

To use secure mode, you must complete the following:

1. Enable secure mode for each environment: You can enable secure mode by editing each of your environments from the **Environments** list of your project in the LaunchDarkly user interface. Secure mode is an environment-wide setting. You can enable secure mode for your environment even if you're also using SDKs other than JavaScript. Enabling secure mode does not cause those SDKs to fail.
2. [Configure your server-side or edge SDK to generate the secure mode hash](#generate-a-secure-mode-hash): Most LaunchDarkly server-side and edge SDKs include a method to compute the secure mode hash for a key. Alternatively, you can compute the hash yourself. To learn how, read [Compute the hash manually](#compute-the-hash-manually). If at any time you reset an environment's SDK key, you will need to regenerate the secure mode hash.
3. [Send the computed secure mode hash for the context or user to LaunchDarkly](#configure-secure-mode-in-javascript-based-sdks): Include the secure mode hash when requesting flag evaluations. The JavaScript-based SDK will send the context or user key and the hash to LaunchDarkly. If the hash doesn’t match, LaunchDarkly returns an error.

<Tip>
  **Enable secure mode during initial setup**

  You can enable secure mode at any time when you use LaunchDarkly SDKs. As a best practice, we recommend that you enable secure mode during initial SDK configuration, because late-stage changes to your SDK configuration may have negative interactions with other settings.
</Tip>

To learn more about the secure mode hash process, read [How to verify secure mode hash](https://support.launchdarkly.com/hc/en-us/articles/14614789065115-How-to-verify-secure-mode-hash).

<Note>
  **Newer versions of LaunchDarkly SDKs replace users with contexts**

  A context is a generalized way of referring to the people, services, machines, or other resources that encounter feature flags in your product. Contexts replace another data object in LaunchDarkly: "users." To learn more, read [Contexts](/docs/home/flags/contexts).

  Creating contexts and evaluating flags based on them is supported in the latest major versions of [most of our SDKs](/docs/sdk). For these SDKs, the code samples on this page include the two most recent versions.
</Note>

## Generate a secure mode hash

Details about generating a secure mode hash are available in the SDK-specific sections below:

* [Server-side SDKs](#server-side-sdks)
* [Edge SDKs](#edge-sdks)

## Server-side SDKs

You can use the following server-side SDKs to generate a secure mode hash:

* [.NET (server-side)](#net-server-side)
* [Go](#go)
* [Haskell](#haskell)
* [Java](#java)
* [Node.js (server-side)](#node-js-server-side)
* [PHP](#php)
* [Python](#python)
* [Ruby](#ruby)
* [Rust](#rust)

### .NET (server-side)

<Accordion title="Expand .NET (server-side) code sample">
  The [`SecureModeHash`](https://launchdarkly.github.io/dotnet-core/pkgs/sdk/server/api/LaunchDarkly.Sdk.Server.LdClient.html#LaunchDarkly_Sdk_Server_LdClient_SecureModeHash_) method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```csharp title=".NET SDK v7.0+ (C#)" lines wrap theme={null}
    var hash = client.SecureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

### Go

<Accordion title="Expand Go code sample">
  The [`SecureModeHash`](https://pkg.go.dev/github.com/launchdarkly/go-server-sdk/v7#LDClient.SecureModeHash) method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```go title="Go SDK v7.13.4+, using LDScopedClient" lines wrap theme={null}
    // There is not a SecureModeHash method in the LDScopedClient,
    // so you need to access the method from the LDClient.
    // Then, pass in the scoped client's current context.
    // LDScopedClient is in beta and may change without notice.
    scopedClient.Client().SecureModeHash(scopedClient.CurrentContext())
    ```

    ```go title="Go SDK v6+, using LDClient" lines wrap theme={null}
    client.SecureModeHash(context)
    ```
  </CodeGroup>
</Accordion>

### Haskell

<Accordion title="Expand Haskell code sample">
  The `secureModeHash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```haskell title="Haskell SDK v4.0" lines wrap theme={null}
    secureModeHash client context
    ```
  </CodeGroup>
</Accordion>

### Java

<Accordion title="Expand Java code sample">
  The [`secureModeHash`](https://launchdarkly.github.io/java-core/lib/sdk/server/com/launchdarkly/sdk/server/LDClient.html#secureModeHash-com.launchdarkly.sdk.LDContext-) method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```java title="Java SDK v6.0+" lines wrap theme={null}
    client.secureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

### Node.js (server-side)

<Accordion title="Expand Node.js (server-side) code sample">
  The `secureModeHash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```js title="Node.js SDK v7.x and later (JavaScript)" lines wrap theme={null}
    client.secureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

### PHP

<Accordion title="Expand PHP code sample">
  The `secureModeHash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```php title="PHP SDK v5.0+" lines wrap theme={null}
    $hash = $client->secureModeHash($context);
    ```
  </CodeGroup>
</Accordion>

### Python

<Accordion title="Expand Python code sample">
  The `SecureModeHash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```python title="Python SDK v8.0+" lines wrap theme={null}
    hash = ldclient.get().secure_mode_hash(context)
    ```
  </CodeGroup>
</Accordion>

### Ruby

<Accordion title="Expand Ruby code sample">
  The `secure_mode_hash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```ruby title="Ruby SDK v7.0+" lines wrap theme={null}
    client.secure_mode_hash(context)
    ```
  </CodeGroup>
</Accordion>

### Rust

<Accordion title="Expand Rust code sample">
  The `secure_mode_hash` method computes an HMAC signature of a context signed with the client's SDK key.

  Here is the method:

  <CodeGroup>
    ```rust title="Rust SDK v3.0" lines wrap theme={null}
    match client.secure_mode_hash(&context) {
        Ok(hash) => println!("Hash: {}", hash),
        Err(e) => eprintln!("Failed to compute hash: {}", e),
    }
    ```

    ```rust title="Rust SDK v2.x" lines wrap theme={null}
    let hash: String = client.secure_mode_hash(&context);
    ```
  </CodeGroup>
</Accordion>

## Edge SDKs

You can use the following edge SDKs to generate a secure mode hash:

* [Cloudflare](#cloudflare)
* [Fastly](#fastly)
* [Vercel](#vercel)

### Cloudflare

<Accordion title="Expand Cloudflare code sample">
  The [`secureModeHash`](https://launchdarkly.github.io/js-core/packages/sdk/cloudflare/docs/classes/LDClient.html#secureModeHash) method computes an HMAC signature of a context signed with the SDK key.

  Here is the method:

  <CodeGroup>
    ```typescript title="TypeScript" lines wrap theme={null}
    const hash = client.secureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

### Fastly

<Accordion title="Expand Fastly code sample">
  The [`secureModeHash`](https://launchdarkly.github.io/js-core/packages/sdk/fastly/docs/classes/LDClient.html#secureModeHash) method computes an HMAC signature of a context signed with the SDK key.

  Here is the method:

  <CodeGroup>
    ```typescript title="TypeScript" lines wrap theme={null}
    const hash = client.secureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

### Vercel

<Accordion title="Expand Vercel code sample">
  The [`secureModeHash`](https://launchdarkly.github.io/js-core/packages/sdk/vercel/docs/classes/LDClient.html#secureModeHash) method computes an HMAC signature of a context signed with the SDK key.

  Here is the method:

  <CodeGroup>
    ```typescript title="TypeScript" lines wrap theme={null}
    const hash = client.secureModeHash(context);
    ```
  </CodeGroup>
</Accordion>

## Compute the hash manually

To compute the hash manually, locate the server-side SDK key for your environment on the **SDK keys** page under **Settings**. Then, compute an HMAC SHA256 hash of the UTF-8 encoding of your context key, using the UTF-8 encoding of your SDK key as a secret, and convert the hash to a hexadecimal string.

Here is a .NET (server-side) example:

<CodeGroup>
  ```csharp title="C#" lines wrap theme={null}
  using System;
  using System.Security.Cryptography;
  using System.Text;

  var encoding = new UTF8Encoding();
  var keyBytes = encoding.GetBytes("YOUR_SDK_KEY");
  var hmacSha256 = new HMACSHA256(keyBytes);
  var hashBytes = hmacSha256.ComputeHash(encoding.GetBytes("example-context-key"));
  var hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
  ```
</CodeGroup>

## Configure secure mode in JavaScript-based SDKs

To use secure mode, you must generate the hash based on a unique identifier for the context. This unique identifier is called a "canonical key" and is a concatenation of the `kind` and `key` attributes, separated by a colon (`:`). For example, if a user context has a key of "example-user-key," this means you must generate the hash using a canonical key of `user:example-user-key`. If the context is a multi-context, the canonical key must include the `key` and `kind` attribute for each context kind. For example, if a multi-context contains an organization context kind and a user context kind, and they have the keys "example-organization-key" and "example-user-key", the canonical key is `organization:example-organization-key:user:example-user-key`.

Secure mode is not compatible with the SDK's ability to automatically generate keys for anonymous contexts because the SDK needs a correctly calculated `hash` value. To learn more, read [Anonymous contexts and users](/docs/sdk/features/anonymous).

In JavaScript-based SDKs, send the computed secure mode hash for your context as the [`hash` attribute](https://launchdarkly.github.io/js-core/packages/sdk/browser/docs/interfaces/LDIdentifyOptions.html#hash) in the `LDOptions` object during client initialization, and as the [`hash` parameter](https://launchdarkly.github.io/js-client-sdk/interfaces/LDClient.html#identify) if subsequently identifying new contexts.

Specifying the computed secure mode hash is supported in the following client-side SDKs:

* [Electron](#electron)
* [JavaScript](#javascript)
* [Node.js (client-side)](#node-js-client-side)
* [React Web](#react-web)
* [Vue](#javascript): The Vue SDK relies on the JavaScript SDK for this functionality.

### Electron

<Accordion title="Expand Electron code sample">
  Here's how to configure or send the computed secure mode hash:

  <CodeGroup>
    ```js title="Electron SDK" lines wrap theme={null}
    // client initialization
    const options = {
      hash: 'example-server-generated-hash',
    };
    const client = LDClient.initialize('example-client-side-id', user, options);

    // identification of new user
    client.identify(newUser, hash, function() {
      console.log("New user's flags available");
    });

    // identification of new user, with a Promise
    client.identify(newUser, hash).then(() => {
      console.log("New user's flags available");
    });
    ```
  </CodeGroup>
</Accordion>

### JavaScript

<Accordion title="Expand JavaScript code sample">
  Here's how to configure or send the computed secure mode hash:

  <CodeGroup>
    ```js title="JavaScript SDK v3.x+" expandable lines wrap theme={null}
    // client initialization
    const options = {
      hash: 'example-server-generated-hash',
    };
    const client = LDClient.initialize('example-client-side-id', context, options);

    try {
      await client.waitForInitialization(5);
      // proceed with successfully initialized client

      // identification of new contexts
      client.identify(newContext, hash, function() {
        console.log("New context's flags available");
      });

    } catch(err) {
      // Client failed to initialized or timed out
      // variation() calls return fallback values until initialization completes
    }

    ```

    ```ts title="JavaScript SDK v3.x+ (TypeScript)" expandable lines wrap theme={null}
    // client initialization
    const context: ld.LDContext = { kind: 'user', key: 'example-context-key' };
    const options: ld.LDOptions = { hash: 'example-server-generated-hash' };
    const client: ld.LDClient = ld.initialize('example-client-side-id', context, options);

    try {
      await client.waitForInitialization(5);
      // proceed with successfully initialized client

      // identification of new contexts
      client.identify(newContext, hash, function() {
        console.log("New context's flags available");
      });

    } catch(err) {
      // Client failed to initialized or timed out
      // variation() calls return fallback values until initialization completes
    }

    ```
  </CodeGroup>
</Accordion>

### Node.js (client-side)

<Accordion title="Expand Node.js (client-side) code sample">
  Here's how to configure or send the computed secure mode hash:

  <CodeGroup>
    ```js title="Node.js (client-side) SDK v3 (JavaScript)" lines wrap theme={null}
    // client initialization
    const options = {
      hash: 'example-server-generated-hash',
    };
    const client = LDClient.initialize('example-client-side-id', context, options);

    // identification of new contexts
    client.identify(newContext, hash, function() {
      console.log("New context's flags available");
    });

    // identification of new contexts, with a Promise
    client.identify(newContext, hash).then(() => {
      console.log("New context's flags available");
    });
    ```
  </CodeGroup>
</Accordion>

### React Web

All context-related functionality provided by the [JavaScript SDK](#javascript) is also available in the React Web SDK.

### Vue

The Vue SDK relies on the [JavaScript SDK](#javascript) for secure mode.
