Claude
Skills
Sign in
Back

keycloak-admin

Included with Lifetime
$97 forever

Keycloak administration including realm management, client configuration, OAuth 2.0 setup, user management with custom attributes, role and group management, theme deployment, and token configuration. Activate for Keycloak Admin API operations, authentication setup, and identity provider configuration.

Backend & APIs

What this skill does


# Keycloak Admin Skill

Comprehensive Keycloak administration for the keycloak-alpha multi-tenant MERN platform with OAuth 2.0 Authorization Code Flow.

## When to Use This Skill

Activate this skill when:
- Setting up Keycloak realms and clients
- Configuring OAuth 2.0 Authorization Code Flow
- Managing users with custom attributes (org_id)
- Deploying custom themes
- Troubleshooting authentication issues
- Configuring token lifetimes and session management

## Keycloak Admin REST API

### Authentication

Use the admin-cli client to obtain an access token:

```bash
# Get admin access token
TOKEN=$(curl -X POST "http://localhost:8080/realms/master/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=admin" \
  -d "password=admin" \
  -d "grant_type=password" \
  -d "client_id=admin-cli" | jq -r '.access_token')

# Use token in subsequent requests
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/admin/realms/master"
```

### Key API Endpoints

| Endpoint | Method | Purpose |
|----------|--------|---------|
| `/admin/realms` | GET | List all realms |
| `/admin/realms/{realm}` | POST | Create realm |
| `/admin/realms/{realm}/clients` | GET/POST | Manage clients |
| `/admin/realms/{realm}/users` | GET/POST | Manage users |
| `/admin/realms/{realm}/roles` | GET/POST | Manage roles |
| `/admin/realms/{realm}/groups` | GET/POST | Manage groups |

## Realm Creation and Configuration

### Create a New Realm

```bash
# Create realm with basic configuration
curl -X POST "http://localhost:8080/admin/realms" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "realm": "lobbi",
    "enabled": true,
    "displayName": "Lobbi Platform",
    "sslRequired": "external",
    "registrationAllowed": false,
    "loginWithEmailAllowed": true,
    "duplicateEmailsAllowed": false,
    "resetPasswordAllowed": true,
    "editUsernameAllowed": false,
    "bruteForceProtected": true,
    "permanentLockout": false,
    "maxFailureWaitSeconds": 900,
    "minimumQuickLoginWaitSeconds": 60,
    "waitIncrementSeconds": 60,
    "quickLoginCheckMilliSeconds": 1000,
    "maxDeltaTimeSeconds": 43200,
    "failureFactor": 30,
    "defaultSignatureAlgorithm": "RS256",
    "revokeRefreshToken": false,
    "refreshTokenMaxReuse": 0,
    "accessTokenLifespan": 300,
    "accessTokenLifespanForImplicitFlow": 900,
    "ssoSessionIdleTimeout": 1800,
    "ssoSessionMaxLifespan": 36000,
    "offlineSessionIdleTimeout": 2592000,
    "accessCodeLifespan": 60,
    "accessCodeLifespanUserAction": 300,
    "accessCodeLifespanLogin": 1800
  }'
```

### Configure Realm Settings

```javascript
// In keycloak-alpha: services/keycloak-service/src/config/realm-config.js
export const realmDefaults = {
  realm: process.env.KEYCLOAK_REALM || 'lobbi',
  enabled: true,
  displayName: 'Lobbi Platform',

  // Security settings
  sslRequired: 'external',
  registrationAllowed: false,
  loginWithEmailAllowed: true,
  duplicateEmailsAllowed: false,

  // Token lifespans (seconds)
  accessTokenLifespan: 300,              // 5 minutes
  accessTokenLifespanForImplicitFlow: 900, // 15 minutes
  ssoSessionIdleTimeout: 1800,           // 30 minutes
  ssoSessionMaxLifespan: 36000,          // 10 hours
  offlineSessionIdleTimeout: 2592000,    // 30 days

  // Login settings
  resetPasswordAllowed: true,
  editUsernameAllowed: false,

  // Brute force protection
  bruteForceProtected: true,
  permanentLockout: false,
  maxFailureWaitSeconds: 900,
  minimumQuickLoginWaitSeconds: 60,
  failureFactor: 30
};
```

## Client Configuration for OAuth 2.0 Authorization Code Flow

### Create Client

```bash
# Create client for Authorization Code Flow
curl -X POST "http://localhost:8080/admin/realms/lobbi/clients" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "lobbi-web-app",
    "name": "Lobbi Web Application",
    "enabled": true,
    "protocol": "openid-connect",
    "publicClient": false,
    "standardFlowEnabled": true,
    "implicitFlowEnabled": false,
    "directAccessGrantsEnabled": false,
    "serviceAccountsEnabled": false,
    "redirectUris": [
      "http://localhost:3000/auth/callback",
      "https://*.lobbi.com/auth/callback"
    ],
    "webOrigins": [
      "http://localhost:3000",
      "https://*.lobbi.com"
    ],
    "attributes": {
      "pkce.code.challenge.method": "S256"
    },
    "defaultClientScopes": [
      "email",
      "profile",
      "roles",
      "web-origins"
    ],
    "optionalClientScopes": [
      "address",
      "phone",
      "offline_access"
    ]
  }'
```

### Client Configuration in keycloak-alpha

```javascript
// In: apps/web-app/src/config/keycloak.config.js
export const keycloakConfig = {
  url: process.env.VITE_KEYCLOAK_URL || 'http://localhost:8080',
  realm: process.env.VITE_KEYCLOAK_REALM || 'lobbi',
  clientId: process.env.VITE_KEYCLOAK_CLIENT_ID || 'lobbi-web-app',
};

// OAuth 2.0 Authorization Code Flow with PKCE
export const authConfig = {
  flow: 'standard',
  pkceMethod: 'S256',
  responseType: 'code',
  scope: 'openid profile email roles',

  // Redirect URIs
  redirectUri: `${window.location.origin}/auth/callback`,
  postLogoutRedirectUri: `${window.location.origin}/`,

  // Token handling
  checkLoginIframe: true,
  checkLoginIframeInterval: 5,
  onLoad: 'check-sso',
  silentCheckSsoRedirectUri: `${window.location.origin}/silent-check-sso.html`
};
```

### Client Secret Management

```bash
# Get client secret
CLIENT_UUID=$(curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/admin/realms/lobbi/clients?clientId=lobbi-web-app" \
  | jq -r '.[0].id')

curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/admin/realms/lobbi/clients/$CLIENT_UUID/client-secret" \
  | jq -r '.value'

# Regenerate client secret
curl -X POST -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8080/admin/realms/lobbi/clients/$CLIENT_UUID/client-secret"
```

## User Management with Custom Attributes

### Create User with org_id

```bash
# Create user with custom org_id attribute
curl -X POST "http://localhost:8080/admin/realms/lobbi/users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "[email protected]",
    "email": "[email protected]",
    "firstName": "John",
    "lastName": "Doe",
    "enabled": true,
    "emailVerified": true,
    "attributes": {
      "org_id": ["org_acme"],
      "tenant_name": ["ACME Corporation"]
    },
    "credentials": [{
      "type": "password",
      "value": "temp_password_123",
      "temporary": true
    }]
  }'
```

### User Service in keycloak-alpha

```javascript
// In: services/user-service/src/controllers/user.controller.js
import axios from 'axios';

export class UserController {

  async createUser(req, res) {
    const { email, firstName, lastName, orgId } = req.body;

    // Get admin token
    const adminToken = await this.getAdminToken();

    // Create user in Keycloak
    const userData = {
      username: email,
      email,
      firstName,
      lastName,
      enabled: true,
      emailVerified: false,
      attributes: {
        org_id: [orgId],
        created_by: [req.user.sub]
      },
      credentials: [{
        type: 'password',
        value: this.generateTemporaryPassword(),
        temporary: true
      }]
    };

    try {
      const response = await axios.post(
        `${process.env.KEYCLOAK_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users`,
        userData,
        { headers: { Authorization: `Bearer ${adminToken}` } }
      );

      // Extract user ID from Location header
      const userId = response.headers.location.split('/').pop();

      // Assign default roles
      await this.assignRoles(userId, ['user'], adminToken);

      // Send verification email
      await this.sendVerificationEmail(userId, adminToken);

      res.status(201).json({ userId, email });
    } catch 

Related in Backend & APIs