From 712c7be06ba24bc427792bfa29d3d7c5c88b06dd Mon Sep 17 00:00:00 2001 From: hc Date: Fri, 20 Feb 2026 11:46:25 +0800 Subject: eheh --- SETUP.md | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 95 +++++++++++++++++++++ 2 files changed, 333 insertions(+) create mode 100644 SETUP.md create mode 100644 docker-compose.yml diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..fafc7a5 --- /dev/null +++ b/SETUP.md @@ -0,0 +1,238 @@ +# OpenLDAP + Keycloak OIDC Lab Setup + +A Docker-based lab for testing SSO with OIDC on Apple Silicon (M1/M2/M3). + +## Quick Start + +```bash +docker compose up -d +``` + + +## Access Points + +| Service | URL | Credentials | +|---------|-----|-------------| +| **Keycloak** | http://localhost:8080 | admin / admin | +| **LDAP Admin** | http://localhost:8081 | See below | +| **OpenLDAP** | ldap://localhost:389 | See below | + +--- + +## Step 1: Login to LDAP Admin + +1. Open http://localhost:8081 +2. Click **"login"** on the left sidebar +3. Enter: + +| Field | Value | +|-------|-------| +| Login DN | `cn=admin,dc=lab,dc=local` | +| Password | `admin123` | + +--- + +## Step 2: Create Test Users in LDAP + +### Option A: Via Command Line + +**1. Create organizational unit for users:** +```bash +printf 'dn: ou=users,dc=lab,dc=local\nobjectClass: organizationalUnit\nou: users\n' | docker exec -i openldap ldapadd -x -H ldap://localhost -D "cn=admin,dc=lab,dc=local" -w admin123 +``` + +**2. Create test user:** +```bash +printf 'dn: cn=testuser,ou=users,dc=lab,dc=local\nobjectClass: inetOrgPerson\ncn: testuser\nsn: User\ngivenName: Test\nuid: testuser\nuserPassword: Password123\nmail: testuser@lab.local\n' | docker exec -i openldap ldapadd -x -H ldap://localhost -D "cn=admin,dc=lab,dc=local" -w admin123 +``` + +**3. Create another user:** +```bash +printf 'dn: cn=jdoe,ou=users,dc=lab,dc=local\nobjectClass: inetOrgPerson\ncn: jdoe\nsn: Doe\ngivenName: John\nuid: jdoe\nuserPassword: Password123\nmail: jdoe@lab.local\n' | docker exec -i openldap ldapadd -x -H ldap://localhost -D "cn=admin,dc=lab,dc=local" -w admin123 +``` + +### Option B: Via LDAP Admin UI + +1. Login to http://localhost:8081 +2. Expand `dc=lab,dc=local` in the tree +3. Click "Create new entry here" +4. Select "Generic: Organisational Unit" → name it `users` +5. Inside `ou=users`, create "Generic: User Account" + +--- + +## Step 3: Configure Keycloak + +### 3.1 Create a Realm + +1. Open http://localhost:8080 +2. Login with `admin` / `admin` +3. Click dropdown (top-left, says "master") → **Create realm** +4. Name: `lab` +5. Click **Create** + +### 3.2 Add LDAP User Federation + +1. Go to **User federation** (left menu, bottom) +2. Click **Add Ldap providers** +3. Fill in: + +| Setting | Value | +|---------|-------| +| UI display name | `OpenLDAP` | +| Vendor | `Other` | +| Connection URL | `ldap://openldap:389` | +| Bind DN | `cn=admin,dc=lab,dc=local` | +| Bind credentials | `admin123` | +| Edit mode | `WRITABLE` | +| Users DN | `ou=users,dc=lab,dc=local` | +| Username LDAP attribute | `uid` | +| RDN LDAP attribute | `cn` | +| UUID LDAP attribute | `entryUUID` | +| User object classes | `inetOrgPerson` | + +4. Click **Save** +5. Click **Action**(top right) dropdown → **Sync all users** + +### 3.3 Verify Users Synced + +1. Go to **Users** (left menu) +2. Click **View all users** +3. You should see `testuser` and `jdoe` + +--- + +## Step 4: Create an OIDC Client + +1. Go to **Clients** → **Create client** +2. Fill in: + - Client type: `OpenID Connect` + - Client ID: `my-test-app` + - Click **Next** +3. Client authentication: `On` +4. Click **Next** +5. Valid redirect URIs: `http://localhost:3000/*` + - Also add: `https://oidcdebugger.com/debug` +6. Click **Save** +7. Go to **Credentials** tab → Copy the **Client secret** + +--- + +## Step 5: Test OIDC + +### OIDC Discovery Endpoint + +``` +http://localhost:8080/realms/lab/.well-known/openid-configuration +``` + +### Test with OIDC Debugger (easiest) + +1. Go to https://oidcdebugger.com +2. Fill in: + +| Field | Value | +|-------|-------| +| Authorize URI | `http://localhost:8080/realms/lab/protocol/openid-connect/auth` | +| Redirect URI | `https://oidcdebugger.com/debug` | +| Client ID | `my-test-app` | +| Scope | `openid profile email` | +| Response type | `code` | + +3. Click **Send Request** +4. Login with `testuser` / `Password123` +5. You'll get an authorization code back + +### Test with curl + +```bash +# Get token using password grant (for testing only) +curl -X POST http://localhost:8080/realms/lab/protocol/openid-connect/token \ + -H "Content-Type: application/x-www-form-urlencoded" \ + -d "client_id=my-test-app" \ + -d "client_secret=YOUR_CLIENT_SECRET" \ + -d "grant_type=password" \ + -d "username=testuser" \ + -d "password=Password123" | jq +``` + +### Decode the Token + +Copy the `access_token` or `id_token` and paste at https://jwt.io to see the claims. + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────┐ +│ Your App / OIDC Debugger │ +└──────────────────┬──────────────────────────┘ + │ OIDC (authorize, token) + ▼ +┌─────────────────────────────────────────────┐ +│ Keycloak :8080 │ +│ (Identity Provider) │ +└──────────────────┬──────────────────────────┘ + │ LDAP bind (auth check) + ▼ +┌─────────────────────────────────────────────┐ +│ OpenLDAP :389 │ +│ (User Directory) │ +└─────────────────────────────────────────────┘ +``` + +--- + +## Useful Commands + +```bash +# View logs +docker compose logs -f + +# List LDAP users +docker exec openldap ldapsearch -x -H ldap://localhost -b "dc=lab,dc=local" -D "cn=admin,dc=lab,dc=local" -w "admin123" + +# Reset user password +docker exec openldap ldappasswd -x -D "cn=admin,dc=lab,dc=local" -w "admin123" -s "NewPass123!" "cn=testuser,ou=users,dc=lab,dc=local" + +# Delete a user +docker exec openldap ldapdelete -x -D "cn=admin,dc=lab,dc=local" -w "admin123" "cn=testuser,ou=users,dc=lab,dc=local" + +# Stop everything +docker compose down + +# Stop and delete all data +docker compose down -v +``` + +--- + +## Troubleshooting + +**Keycloak can't connect to LDAP:** +- Verify OpenLDAP is running: `docker compose ps` +- Test connection: `docker exec keycloak curl -v ldap://openldap:389` + +**Users not syncing:** +- Make sure `ou=users` exists in LDAP +- Check Users DN is: `ou=users,dc=lab,dc=local` +- Try "Sync all users" again in Keycloak + +**LDAP Admin won't login:** +- Use full DN: `cn=admin,dc=lab,dc=local` +- Password: `admin123` + +**Port 389 already in use:** +- Change port in docker-compose.yml: `"3389:389"` +- Update Keycloak connection URL accordingly + +--- + +## Next Steps + +- [ ] Test SAML SSO (Keycloak supports both OIDC and SAML) +- [ ] Add MFA/2FA in Keycloak +- [ ] Try social login (Google, GitHub) alongside LDAP users +- [ ] Build a sample app that uses OIDC login +- [ ] Explore Keycloak themes and branding diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ef5a7b7 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,95 @@ +services: + # =================== + # OpenLDAP (ARM-native, works great on M1/M2/M3) + # =================== + openldap: + image: osixia/openldap:1.5.0 + container_name: openldap + environment: + - LDAP_ORGANISATION=Lab + - LDAP_DOMAIN=lab.local + - LDAP_BASE_DN=dc=lab,dc=local + - LDAP_ADMIN_PASSWORD=admin123 + - LDAP_TLS=false + ports: + - "389:389" + - "636:636" + volumes: + - openldap-data:/var/lib/ldap + - openldap-config:/etc/ldap/slapd.d + restart: unless-stopped + + # =================== + # Keycloak (OIDC/SAML Provider) + # =================== + keycloak: + image: quay.io/keycloak/keycloak:latest + container_name: keycloak + environment: + - KEYCLOAK_ADMIN=admin + - KEYCLOAK_ADMIN_PASSWORD=admin + - KC_HTTP_ENABLED=true + - KC_HOSTNAME_STRICT=false + ports: + - "8080:8080" + command: start-dev + depends_on: + - openldap + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "exec 3<>/dev/tcp/localhost/8080"] + interval: 5s + timeout: 5s + retries: 12 + + # Disables HTTPS requirement and creates lab realm + keycloak-init: + image: curlimages/curl:latest + container_name: keycloak-init + depends_on: + keycloak: + condition: service_healthy + entrypoint: /bin/sh + command: + - -c + - | + echo "Waiting for Keycloak..." + sleep 10 + echo "Getting admin token..." + TOKEN=$$(curl -s -X POST "http://keycloak: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" | sed 's/.*"access_token":"\([^"]*\)".*/\1/') + echo "Disabling SSL on master realm..." + curl -s -X PUT "http://keycloak:8080/admin/realms/master" \ + -H "Authorization: Bearer $$TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"sslRequired":"NONE"}' + echo "Creating lab realm..." + curl -s -X POST "http://keycloak:8080/admin/realms" \ + -H "Authorization: Bearer $$TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"realm":"lab","enabled":true,"sslRequired":"NONE"}' + echo "Done - master and lab realms ready with SSL disabled" + restart: "no" + + # =================== + # LDAP Admin UI (browse LDAP visually) + # =================== + ldap-admin: + image: osixia/phpldapadmin + container_name: ldap-admin + environment: + - PHPLDAPADMIN_LDAP_HOSTS=openldap + - PHPLDAPADMIN_HTTPS=false + ports: + - "8081:80" + depends_on: + - openldap + restart: unless-stopped + +volumes: + openldap-data: + openldap-config: -- cgit