# Creating and Configuring Clients in Keycloak

A <span class="s2">**client**</span> in Keycloak represents an application or service that uses Keycloak to authenticate users. Clients can be web apps, REST APIs, mobile apps, or even CLI tools. This guide explains how to create and configure clients through the Admin Console, REST API, and CLI (Docker), and also includes roles, best practices, and common troubleshooting steps.

## **Creating Clients via Keycloak Admin Console**

This is the simplest way to register and configure a client visually.

#### **Access the Admin Console**

Log in to:

```
http://<your-keycloak-domain>/admin/
```

Choose the realm where the client should be added.

#### **Add a New Client**

1. <span class="s1">Go to </span>**Clients &gt; Create**
2. Fill in the fields:
    
    
    - <span class="s1">**Client ID**</span>: A unique name, e.g., <span class="s2">frontend-app</span> or <span class="s2">api-service</span>
    - <span class="s1">**Client Type**</span>: Choose between <span class="s2">OpenID Connect</span> (default) or <span class="s2">SAML</span>
    - <span class="s1">**Root URL**</span>: The application base URL (e.g., <span class="s2">http://localhost:3000</span>)
3. Click <span class="s1">**Next**</span>, then <span class="s1">**Save**</span>[![image.png](https://docs.elest.io/uploads/images/gallery/2025-06/scaled-1680-/gqaimage.png)](https://docs.elest.io/uploads/images/gallery/2025-06/gqaimage.png)

#### **Configure Client Settings**

- Go to the <span class="s1">**Settings**</span> tab for the client:
    
    
    - <span class="s1">**Access Type**</span><span class="s2">: Choose </span>public<span class="s2">, </span>confidential<span class="s2">, or </span>bearer-only
    - <span class="s1">**Valid Redirect URIs**</span>: Add allowed redirect URLs (e.g., <span class="s2">http://localhost:3000/\*</span>)
    - <span class="s1">**Web Origins**</span>: Add <span class="s2">\*</span> or specific origins allowed to call this client
    - <span class="s1">**Standard Flow Enabled**</span>: Enable for browser-based login
    - <span class="s1">**Direct Access Grants**</span>: Enable if using password grant from API
- Save the changes

## **Creating Clients via Keycloak REST API**

#### **Get Access Token**

```bash
curl -X POST "https://<keycloak-domain>/realms/master/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=admin" \
  -d "password=admin-password" \
  -d "grant_type=password" \
  -d "client_id=admin-cli"
```

<span class="s1">Save the </span>access\_token<span class="s1">.</span>

#### **Create a Client**

```bash
curl -X POST "https://<keycloak-domain>/admin/realms/<realm>/clients" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "my-app",
    "enabled": true,
    "publicClient": false,
    "redirectUris": ["http://localhost:3000/*"],
    "webOrigins": ["http://localhost:3000"],
    "protocol": "openid-connect"
  }'
```

This creates a confidential client named <span class="s1">my-app</span>.

## **Creating Clients via Docker CLI** 

#### **Step into the Container**

```
docker exec -it keycloak bash
```

#### **Authenticate and Create Client**

```bash
/opt/keycloak/bin/kcadm.sh config credentials \
  --server http://localhost:8080 \
  --realm master --user admin --password admin

/opt/keycloak/bin/kcadm.sh create clients -r <realm> \
  -s clientId=my-cli-client \
  -s enabled=true \
  -s publicClient=false \
  -s redirectUris='["http://localhost:3000/*"]' \
  -s webOrigins='["http://localhost:3000"]'
```

#### **Required Permissions for Client Management**

- Requires <span class="s1">manage-clients</span> or <span class="s1">admin</span> role in the realm
- Token used via REST or CLI must be scoped to allow client creation

To grant roles via Admin Console:

```
Users > admin > Role Mappings > Realm Roles > Assign 'manage-clients'
```

## **Best Practices for Client Configuration**

- **Use Confidential Clients for Backends:** Set <span class="s2">publicClient = false</span> and use <span class="s2">client\_secret</span> for server-to-server communication.
- **Use Public Clients for SPAs:** Frontend apps using redirect flows should be marked as <span class="s2">publicClient = true</span>.
- **Set Narrow Redirect URIs:** Avoid using wildcards like <span class="s2">\*</span> unless absolutely necessary. Use precise URIs for better security.
- **Limit Token Lifespans:** Go to <span class="s3">**Realm Settings &gt; Tokens**</span> and configure access and refresh token lifetimes.
- **Rotate Client Secrets Regularly:** Manually rotate secrets or use automation for higher security compliance.
- **Use Roles and Mappers for RBAC:** Assign client roles and use <span class="s3">**protocol mappers**</span> to inject them into access tokens for authorization checks.

## **Common Issues and Troubleshooting**

<table border="1" id="bkmrk-issue-possible-cause" style="border-collapse: collapse; border-color: rgb(0, 0, 0);"><thead><tr><th style="border-color: rgb(0, 0, 0);">**Issue**

</th><th style="border-color: rgb(0, 0, 0);">**Possible Cause**

</th><th style="border-color: rgb(0, 0, 0);">**Solution**

</th></tr></thead><tbody><tr><td style="border-color: rgb(0, 0, 0);">Invalid redirect URI

</td><td style="border-color: rgb(0, 0, 0);">Redirect URI doesn’t match registered value

</td><td style="border-color: rgb(0, 0, 0);">Ensure exact match in <span class="s1">**Valid Redirect URIs**</span>

</td></tr><tr><td style="border-color: rgb(0, 0, 0);">Client not visible after creation

</td><td style="border-color: rgb(0, 0, 0);">UI or API delay

</td><td style="border-color: rgb(0, 0, 0);">Refresh or re-login to see updated clients

</td></tr><tr><td style="border-color: rgb(0, 0, 0);">Access token doesn’t include roles

</td><td style="border-color: rgb(0, 0, 0);">Missing mappers

</td><td style="border-color: rgb(0, 0, 0);">Add protocol mapper for <span class="s1">client roles</span> under <span class="s2">**Client &gt; Mappers**</span>

</td></tr><tr><td style="border-color: rgb(0, 0, 0);"><span class="s1">403 Forbidden</span> when using client credentials

</td><td style="border-color: rgb(0, 0, 0);">Client type is public or secret is wrong

</td><td style="border-color: rgb(0, 0, 0);">Verify <span class="s1">publicClient=false</span> and check the client secret

</td></tr><tr><td style="border-color: rgb(0, 0, 0);">Invalid client credentials<span class="s1"> error</span>

</td><td style="border-color: rgb(0, 0, 0);">Wrong client ID or secret

</td><td style="border-color: rgb(0, 0, 0);">Verify spelling and match values from Admin Console

</td></tr></tbody></table>