# kcContextExclusionsFtl

[Keycloakify shifts page generation from the backend to the client](https://github.com/keycloakify/keycloakify/discussions/346#discussioncomment-5889791). To achieve this, Keycloakify creates a global `kcContext` object, which holds the necessary information for generating HTML pages.

This object contains no sensitive data—only the information that the Keycloak team considers essential for rendering the various login pages. Additionally, if you have custom plugins, such as [keycloak-email-whitelisting](https://github.com/micedre/keycloak-mail-whitelisting), they may introduce additional values into this object.

<figure><img src="https://2643300760-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F4Ls5iTdfTS2xECgBfw90%2Fuploads%2Fgit-blob-23b31b9d77ee51e218649b57d6e061e9b700ff93%2Fimage%20(186).png?alt=media" alt=""><figcaption><p>A typical kcContext for the register.ftl page</p></figcaption></figure>

If you'd like to prevent some values of the FreeMarker context from being forwarded to the client you can do it with the `kcContextExclusionsFtl` option.

Let's say in this example that we would like to exclude:

* `kcContext.keycloakifyVersion`
* `kcContext.realm.actionTokenGeneratedByUserLifespanMinutes` in the register.ftl page
* `kcContext.realm.idpVerifyAccountLinkActionTokenLifespanMinutes` in the register.ftl page

This is how you would do it:

{% tabs %}
{% tab title="Vite" %}

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { keycloakify } from "keycloakify/vite-plugin";

// https://vitejs.dev/config/
export default defineConfig({
    plugins: [
        react(),
        keycloakify({
            // ...
<strong>            kcContextExclusionsFtl: `
</strong>
<strong>                &#x3C;#if (
</strong><strong>                    xKeycloakify.pageId == "register.ftl" &#x26;&#x26;
</strong><strong>                    [
</strong><strong>                        "actionTokenGeneratedByUserLifespanMinutes", 
</strong><strong>                        "idpVerifyAccountLinkActionTokenLifespanMinutes"
</strong><strong>                    ]?seq_contains(key) &#x26;&#x26;
</strong><strong>                    areSamePath(path, ["realm"])
</strong><strong>                )>
</strong><strong>                    &#x3C;#continue>
</strong><strong>                &#x3C;/#if>
</strong>
<strong>                &#x3C;#if xKeycloakify.keycloakifyVersion != "__hidden__">
</strong><strong>                    &#x3C;#assign xKeycloakify = xKeycloakify + { "keycloakifyVersion": "__hidden__" }>
</strong><strong>                &#x3C;/#if>
</strong>
<strong>            `
</strong>        })
    ]
});
</code></pre>

{% hint style="info" %}
You can also provide a path to a .ftl file instead of inlining the ftl code in your vite.config.ts file.
{% endhint %}
{% endtab %}

{% tab title="Webpack" %}
{% code title="kcContextExclusions.ftl" %}

```ftl
<#if (
    xKeycloakify.pageId == "register.ftl" &&
    [
        "actionTokenGeneratedByUserLifespanMinutes", 
        "idpVerifyAccountLinkActionTokenLifespanMinutes"
    ]?seq_contains(key) &&
    areSamePath(path, ["realm"])
)>
    <#continue>
</#if>

<#if xKeycloakify.keycloakifyVersion != "__hidden__">
    <#assign xKeycloakify = xKeycloakify + { "keycloakifyVersion": "__hidden__" }>
</#if>
```

{% endcode %}

<pre class="language-json" data-title="package.json"><code class="lang-json">{
    "keycloakify": {
        // ...
<strong>        "kcContextExclusionsFtl": "./kcContextExclusions.ftl"
</strong>    }
}
</code></pre>

{% endtab %}
{% endtabs %}

To test/debug your exclusion when you are running `npx keycloakify start-keycloak` you can open the file

`dist_keycloak/theme/<theme_name>/login/login.ftl`

Your custom exclusion are injected around line 300. You can edit this code and reload the page immediately.

## Taking full control of how the KcContext is generated

If you feel limited by this option you can take ownership of the FreeMarker template that generates the kcContext. Let's see how it can be done through an example.\
\
Some values, like for example the realm attributes (kcContext.realm.attributes) are explicitely excluded from the KcContext.

In the following video we explore how to include them back.

{% embed url="<https://www.youtube.com/watch?v=WdSPrpFObhg>" %}

Note that in the video we includes **all** the realm attributes. We might want to expose only a specific set of values. For this we could do:

{% code title="node\_modules/keycloakify/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl" %}

```diff
-    ) || (
-        key == "attributes" &&
-        areSamePath(path, ["realm"])
-    ) || (
+    ) || (
+        areSamePath(path, ["realm", "attributes"]) &&
+        !["myFirstAttribute", "mySecondAttribute"]?seq_contains(key)
+    ) || (
```

{% endcode %}

We could also chose to include only the realm attributes with a specific prefix, for example `theme_`:

{% code title="node\_modules/keycloakify/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl" %}

```diff
-    ) || (
-        key == "attributes" &&
-        areSamePath(path, ["realm"])
-    ) || (
+    ) || (
+        areSamePath(path, ["realm", "attributes"]) &&
+        !key?starts_with("theme_")
+    ) || (
```

{% endcode %}

## Setting up patch-package

As explained in the video:

Add [patch-package](https://www.npmjs.com/package/patch-package) add dev dependency

```bash
yarn add --dev patch-package
```

Edit the FreeMarker template that generates the KcContext in:

**node\_modules/keycloakify/src/bin/keycloakify/generateFtl/kcContextDeclarationTemplate.ftl**

You can then create a diff for your changes by running:

```bash
npx patch-package keycloakify
```

Then add a postinstall script to your package.json:

<pre class="language-json" data-title="package.json"><code class="lang-json">{
    "name": "keycloakify-starter",
    "scripts": {
<strong>        "postinstall": "patch-package",
</strong>        "dev": "vite",
    ...
}
</code></pre>

Commit the **patch/** directory that have been created by patch-package.
