A simple setup for running Keycloak in GitHub Codespaces for development work.
- Increase your Codespace timeout limit for inactivity as follows:
- Go to GitHub > Settings > Codespaces
- Under
Idle timeout
, increase the value (max is 240 minutes)
-
Open in Codespaces: Click the green "Code" button in GitHub and select "Create codespace on main" OR click the button below:
-
Wait for setup: The environment will automatically set up Keycloak with PostgreSQL
-
Access Keycloak: Once ready, open
http://localhost:8080/admin
in your browser -
On subsequent Codespace starts, run
docker-compose up -d
All references to http://localhost:8080 should use the Codespace forwarded port (e.g. https://animated-space-succotash-wr545qpxc9qgx-8080.app.github.dev
).
- Change the port visibility from private to public
- Log into the Admin Console at
http://localhost:8080/admin
with Username:admin
, Password:admin
- The first thing you should do is create a realm as it is not recommended to use the master realm for anything other than managing Keycloak itself (e.g., managing other realms and admin users)
- Your JWKS URL is: https://your-keycloak-url/realms/{realm-name}/protocol/openid-connect/certs
- Your token URL is: https://your-keycloak-url/realms/{realm-name}/protocol/openid-connect/token
- Your Authorization URL is: https://your-keycloak-url/auth/realms/{realm-name}/protocol/openid-connect/auth
- Admin Console:
http://localhost:8080/admin
- Username:
admin
- Password:
admin
- Keycloak 23.0: Latest stable version running in development mode
- PostgreSQL 15: Database backend for Keycloak
- Docker Compose: Easy container orchestration
- VS Code Extensions: JSON, YAML, and Docker support
The environment starts automatically when you open the Codespace. If you need to restart:
docker-compose down
docker-compose up -d
- Keycloak Admin Console: http://localhost:8080/admin
- Keycloak Account Console: http://localhost:8080/realms/master/account
- PostgreSQL: localhost:5432
Place custom themes in the themes/
directory. They'll be automatically mounted into Keycloak.
Important: By default, PostgreSQL data persists between Codespace sessions using a bind mount to ./postgres-data/
. This directory is stored in the Codespace's persistent storage.
However, if the Codespace is deleted or rebuilt, all data will be lost. For important configurations:
# Export a specific realm
docker-compose exec keycloak /opt/keycloak/bin/kc.sh export --dir /opt/keycloak/data/import --realm your-realm-name
# Export all realms
docker-compose exec keycloak /opt/keycloak/bin/kc.sh export --dir /opt/keycloak/data/import
Place your realm JSON files in the imports/
directory. They'll be available at /opt/keycloak/data/import
inside the container.
Connect to PostgreSQL directly:
docker-compose exec keycloak-db psql -U keycloak -d keycloak
The setup uses development-friendly configurations:
- Hostname restrictions disabled
- HTTPS not enforced
- Detailed logging enabled
- Metrics and health endpoints enabled
- Check if ports 8080 or 5432 are already in use
- Restart the containers:
docker-compose restart
- Ensure Keycloak is fully started (check logs:
docker-compose logs keycloak
) - Verify port forwarding is working in Codespaces
- Check if PostgreSQL is running:
docker-compose ps
- Restart database:
docker-compose restart keycloak-db
# View logs
docker-compose logs -f keycloak
docker-compose logs -f keycloak-db
# Restart services
docker-compose restart
# Stop everything
docker-compose down
# Start fresh (removes data)
docker-compose down -v
docker-compose up -d
- Create your first realm
- Configure authentication flows
- Set up user federation
- Develop custom themes
- Integrate with your applications
https://your-keycloak-url/realms/{realm-name}/protocol/openid-connect/certs
https://your-keycloak-url/realms/{realm-name}/protocol/openid-connect/token
https://www.keycloak.org/docs-api/latest/rest-api/index.html
Create a Dedicated Service Account Client This is more secure for programmatic access:
Create a client in the Keycloak admin console:
Go to Clients → Create Client Client ID: api-client Client authentication: ON Service accounts roles: ON
Get client credentials from the Credentials tab Use client credentials grant:
# Replace with your actual client secret
CLIENT_SECRET="your-client-secret-here"
TOKEN_RESPONSE=$(curl -s -X POST \
'https://your-codespace-url.app.github.dev/realms/master/protocol/openid-connect/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials' \
-d 'client_id=api-client' \
-d 'client_secret='$CLIENT_SECRET)
ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
You will need to assign roles to your api-client
service account to access the Admin REST API. Here's how to set it up:
- Go to your realm (
lbrenman
) in Keycloak admin console - Navigate to: Clients →
api-client
→ Service Account Roles tab - Assign roles depending on what level of access you need:
- Client roles → Select
realm-management
from dropdown - Assign:
realm-admin
This gives full administrative access to the realm.
Instead of realm-admin
, assign only what you need:
For user management:
view-users
manage-users
create-user
For client management:
view-clients
manage-clients
For realm configuration:
view-realm
manage-realm
For identity providers:
view-identity-providers
manage-identity-providers
After assigning roles, test with your token:
# Get token
TOKEN_RESPONSE=$(curl -s --location 'https://animated-space-succotash-wr545qpxc9qgx-8080.app.github.dev/realms/lbrenman/protocol/openid-connect/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=client_credentials' \
--data 'client_id=api-client' \
--data 'client_secret=NsFVZCo0Zf8TB4DfwN6cRzSgobgUBbs6')
ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
# Test API calls
# List users
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
'https://animated-space-succotash-wr545qpxc9qgx-8080.app.github.dev/admin/realms/lbrenman/users'
# Get realm info
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
'https://animated-space-succotash-wr545qpxc9qgx-8080.app.github.dev/admin/realms/lbrenman'
Here are the main realm-management roles and what they allow:
Role | Permissions |
---|---|
realm-admin |
Full administrative access |
manage-users |
Create, update, delete users |
view-users |
Read user information |
manage-clients |
Create, update, delete clients |
view-clients |
Read client information |
manage-realm |
Configure realm settings |
view-realm |
Read realm configuration |
manage-identity-providers |
Configure SSO providers |
view-identity-providers |
Read SSO provider configs |
You can also check what roles your service account has by decoding the JWT token:
# Decode the token payload (requires base64 and jq)
echo $ACCESS_TOKEN | cut -d'.' -f2 | base64 -d 2>/dev/null | jq '.realm_access.roles'
Start with realm-admin
for full access, then narrow it down to specific roles based on your actual needs for better security.
Once you have an access token:
# List all realms
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
'https://your-codespace-url.app.github.dev/admin/realms'
# Get users in master realm
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
'https://your-codespace-url.app.github.dev/admin/realms/master/users'
# Create a new user
curl -X POST \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "testuser",
"enabled": true,
"firstName": "Test",
"lastName": "User",
"email": "[email protected]"
}' \
'https://your-codespace-url.app.github.dev/admin/realms/master/users'
Here's a simple script to test the API access:
#!/bin/bash
KEYCLOAK_URL="https://your-codespace-url.app.github.dev"
# Get token using admin credentials
TOKEN_RESPONSE=$(curl -s -X POST \
"$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password' \
-d 'client_id=admin-cli' \
-d 'username=admin' \
-d 'password=admin')
if [ $? -eq 0 ]; then
ACCESS_TOKEN=$(echo $TOKEN_RESPONSE | jq -r '.access_token')
if [ "$ACCESS_TOKEN" != "null" ] && [ "$ACCESS_TOKEN" != "" ]; then
echo "✅ Successfully obtained access token"
# Test API call
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
"$KEYCLOAK_URL/admin/realms" | jq '.[].realm'
else
echo "❌ Failed to get access token"
echo $TOKEN_RESPONSE | jq '.'
fi
else
echo "❌ Failed to connect to Keycloak"
fi
You can use the admin API with OAuth2 to create and manage clients.
For Dynamic Client Registration you can also create an Initial access token (Client -> Initial access token) and make a call to the /realms/<realm>/clients-registrations/openid-connect
endpoint using this Bearer token.
For example:
curl --location 'https://cuddly-train-r44r5655jfx7xv-8080.app.github.dev/realms/lbrenman/clients-registrations/openid-connect' \
--header 'Content-Type: application/json' \
--data '{
"client_name": "my-test-client",
"token_endpoint_auth_method": "client_secret_basic",
"redirect_uris":[
"https://test123.com/callback"
],
"grant_types":[
"client_credentials"
]
}'
With response:
{
"redirect_uris": [
"https://test123.com/callback"
],
"token_endpoint_auth_method": "client_secret_basic",
"grant_types": [
"authorization_code",
"client_credentials"
],
"response_types": [
"code",
"none"
],
"client_id": "f5f02504-ebc7-47b4-9082-84798c766d8b",
"client_secret": "7V63XOsFX97p9I7Z4HimBIhD8sKyTFpM",
"client_name": "my-client10",
"scope": "address phone offline_access microprofile-jwt",
"subject_type": "public",
"request_uris": [],
"tls_client_certificate_bound_access_tokens": false,
"dpop_bound_access_tokens": false,
"post_logout_redirect_uris": [
"https://test123.com/callback"
],
"client_id_issued_at": 1748879746,
"client_secret_expires_at": 0,
"registration_client_uri": "https://cuddly-train-r44r5655jfx7xv-8080.app.github.dev/realms/lbrenman/clients-registrations/openid-connect/f5f02504-ebc7-47b4-9082-84798c766d8b",
"registration_access_token": "eyJh...nISuE-54",
"backchannel_logout_session_required": false,
"require_pushed_authorization_requests": false,
"frontchannel_logout_session_required": false
}