# Keycloak Integration

> Integrate Keycloak as your identity provider for unified authentication across all your applications with Edesy Email.

Source: https://edesy.in/docs/email-platform/advanced/keycloak-integration

This guide explains how to integrate Keycloak as your identity provider for unified authentication across all your applications, similar to Zoho's unified login system.

## Overview

Edesy Email already has built-in OpenID Connect (OIDC) support, and Keycloak is a fully-compliant OIDC provider. This means you can integrate Keycloak without any code changes - just configuration.

## Benefits of Using Keycloak

- **Unified Login**: Single sign-on (SSO) across all your applications
- **Centralized User Management**: Manage all users in one place
- **Multi-Factor Authentication**: Built-in 2FA/MFA support
- **Identity Brokering**: Connect to other identity providers (Google, Facebook, SAML, etc.)
- **Fine-grained Authorization**: Role-based access control (RBAC)
- **User Federation**: Connect to LDAP/Active Directory

## Prerequisites

- Running Keycloak instance (self-hosted or cloud)
- Admin access to your Keycloak realm
- Edesy Email installation

## Step 1: Configure Keycloak

### 1.1 Create a Realm (Optional)

If you want a dedicated realm for your applications:

1. Log in to Keycloak Admin Console
2. Click the realm dropdown (top-left) and select **Add realm**
3. Name it (e.g., "mycompany" or "production")
4. Click **Create**

### 1.2 Create a Client for Edesy Email

1. In your Keycloak realm, go to **Clients** -> **Create**
2. Configure the client:
   - **Client ID**: `edesy-email` (or your preferred name)
   - **Client Protocol**: `openid-connect`
   - Click **Save**

3. Configure Client Settings:
   - **Access Type**: `confidential`
   - **Standard Flow Enabled**: `ON`
   - **Direct Access Grants Enabled**: `ON` (optional)
   - **Valid Redirect URIs**:
     ```
     https://your-edesy-email-domain.com/api/auth/login/openid/callback
     http://localhost:3000/api/auth/login/openid/callback
     ```
   - **Web Origins**: `https://your-edesy-email-domain.com` or `*` for development
   - Click **Save**

4. Get Client Credentials:
   - Go to the **Credentials** tab
   - Copy the **Secret** - you'll need this later

### 1.3 Configure Client Scopes (Optional but Recommended)

Ensure the following scopes are available:
1. Go to **Client Scopes**
2. Make sure these are included: `openid`, `email`, `profile`
3. In your client's **Client Scopes** tab, ensure these are added as **Default Client Scopes**

### 1.4 Configure User Attributes Mappers

To ensure proper user information is passed to Edesy Email:

1. Go to your client -> **Mappers** tab
2. Create the following mappers if they don't exist:

**Email Mapper:**
- Name: `email`
- Mapper Type: `User Property`
- Property: `email`
- Token Claim Name: `email`
- Claim JSON Type: `String`
- Add to ID token: `ON`
- Add to access token: `ON`
- Add to userinfo: `ON`

**First Name Mapper:**
- Name: `given name`
- Mapper Type: `User Property`
- Property: `firstName`
- Token Claim Name: `given_name`
- Claim JSON Type: `String`
- Add to ID token: `ON`

**Last Name Mapper:**
- Name: `family name`
- Mapper Type: `User Property`
- Property: `lastName`
- Token Claim Name: `family_name`
- Claim JSON Type: `String`
- Add to ID token: `ON`

**Picture Mapper (Optional):**
- Name: `picture`
- Mapper Type: `User Attribute`
- User Attribute: `picture`
- Token Claim Name: `picture`
- Claim JSON Type: `String`
- Add to ID token: `ON`

## Step 2: Configure Edesy Email Environment Variables

Update your `.env` file or environment configuration:

```bash
# Set OpenID as the auth driver
AUTH_DRIVER=openid

# OpenID Connect Configuration
AUTH_OPENID_NAME=Login with Keycloak
AUTH_OPENID_ISSUER_URL=https://your-keycloak-domain.com/realms/your-realm-name
AUTH_OPENID_CLIENT_ID=edesy-email
AUTH_OPENID_CLIENT_SECRET=your-client-secret-from-keycloak
# Note: AUTH_OPENID_REDIRECT_URI is automatically set to {API_BASE_URL}/auth/login/openid/callback

# Optional: Domain whitelist (comma-separated list of allowed email domains)
# Leave empty to allow all domains
AUTH_OPENID_DOMAIN=

# Base URLs (make sure these are correct)
BASE_URL=https://your-edesy-email-domain.com
API_BASE_URL=https://your-edesy-email-domain.com/api
```

### Configuration Details

**AUTH_OPENID_ISSUER_URL**: This is your Keycloak realm's issuer URL. Format:
- `https://{keycloak-host}/realms/{realm-name}`
- Example: `https://auth.mycompany.com/realms/production`
- For local development: `http://localhost:8080/realms/master`

You can verify this URL by visiting: `{ISSUER_URL}/.well-known/openid-configuration`

**AUTH_OPENID_CLIENT_ID**: The Client ID you created in Keycloak (e.g., `edesy-email`)

**AUTH_OPENID_CLIENT_SECRET**: Found in Keycloak under Clients -> {your-client} -> Credentials tab

**AUTH_OPENID_DOMAIN**: Optional. If you want to restrict login to specific email domains:
- Single domain: `mycompany.com`
- Multiple domains: `company1.com,company2.com`
- All domains: Leave empty or omit

## Step 3: Restart Edesy Email

After updating your environment variables:

```bash
# If using Docker
docker-compose restart

# If running directly
npm run start
```

## Step 4: Test the Integration

1. Navigate to your Edesy Email login page: `https://your-edesy-email-domain.com/login`
2. You should see "Login with Keycloak" (or whatever you set in `AUTH_OPENID_NAME`)
3. Click the button - you'll be redirected to Keycloak
4. Log in with your Keycloak credentials
5. After successful authentication, you'll be redirected back to Edesy Email

## Advanced Configuration

### Multiple Authentication Methods

You can enable multiple authentication methods simultaneously:

```bash
# Enable both OpenID (Keycloak) and Email authentication
AUTH_DRIVER=openid,email

# Email auth settings
AUTH_EMAIL_FROM=noreply@yourcompany.com
AUTH_EMAIL_SMTP_HOST=smtp.yourcompany.com
AUTH_EMAIL_SMTP_PORT=587
AUTH_EMAIL_SMTP_SECURE=true
AUTH_EMAIL_SMTP_USERNAME=your-smtp-username
AUTH_EMAIL_SMTP_PASSWORD=your-smtp-password
```

### Multi-Organization Support

If you're using Edesy Email's multi-organization feature, you can configure different auth methods per organization:

```bash
# Enable multi-org
MULTI_ORG=true

# Set the default auth driver
AUTH_DRIVER=multi
```

Organizations can then have their own auth configurations in the database.

### Domain-based Routing

To automatically route users based on their email domain (similar to Zoho):

1. Set up the **Multi** auth driver:
```bash
AUTH_DRIVER=multi
AUTH_MULTI_NAME=Login
```

2. Configure different organizations with different auth methods
3. When users enter their email, they'll be routed to the appropriate auth method

## Unified Authentication Across Your Apps

To achieve Zoho-style unified authentication:

### 1. Use the Same Keycloak Realm

Configure all your applications to use the same Keycloak realm. This way:
- Users log in once
- They're automatically authenticated across all apps
- Single logout works across all apps

### 2. Configure Each Application as a Keycloak Client

For each application:
1. Create a new client in Keycloak
2. Set appropriate redirect URIs
3. Configure the same user attribute mappers

### 3. Enable Single Sign-On (SSO)

Keycloak automatically provides SSO. When a user logs into one application:
- Keycloak creates a session
- When they visit another app using the same Keycloak realm
- They're automatically logged in (if the session is still active)

### 4. Implement Single Sign-Out (Optional)

For proper single sign-out across all apps, you may need to:
1. Enable backchannel logout in Keycloak clients
2. Implement logout endpoints in your applications
3. Configure logout redirect URIs

## Troubleshooting

### Error: "OpenID validation error"

**Cause**: Usually a mismatch in configuration

**Solutions**:
1. Verify the issuer URL is correct and accessible
2. Check that the client secret matches
3. Ensure the redirect URI in Keycloak matches exactly: `{API_BASE_URL}/auth/login/openid/callback`
4. Check Keycloak logs for more details

### Error: "Missing email in claims"

**Cause**: Email not included in the ID token

**Solutions**:
1. Ensure the email scope is added to the client
2. Check that email mappers are configured correctly
3. Verify the user has an email address in Keycloak

### Error: "Invalid redirect URI"

**Cause**: The redirect URI in the auth request doesn't match Keycloak configuration

**Solutions**:
1. Check `BASE_URL` and `API_BASE_URL` in your `.env` file
2. Verify the redirect URI in Keycloak includes: `{API_BASE_URL}/auth/login/openid/callback`
3. Make sure there are no trailing slashes causing mismatches

### Users Can't Log In

**Solutions**:
1. Check if the user exists in Keycloak
2. Verify the user's email is verified (if required by your realm)
3. Check if there are any required actions on the user account
4. Verify the client has the correct access type (confidential)

### Session Issues

If users are getting logged out frequently:
1. Check Keycloak's session timeout settings (Realm Settings -> Tokens)
2. Verify `APP_SECRET` in Edesy Email is set correctly
3. Check if cookies are being blocked (HTTPS, SameSite issues)

## Security Best Practices

1. **Use HTTPS**: Always use HTTPS in production for both Keycloak and Edesy Email
2. **Rotate Secrets**: Regularly rotate client secrets
3. **Restrict Domains**: Use `AUTH_OPENID_DOMAIN` to limit which domains can log in
4. **Enable MFA**: Configure multi-factor authentication in Keycloak
5. **Session Timeouts**: Set appropriate session timeout values
6. **Monitor Logs**: Regularly review authentication logs in both systems
7. **Use Strong Passwords**: Enforce password policies in Keycloak
8. **Limit Client Scope**: Only request the scopes your application needs

## Example: Complete Local Development Setup

### Keycloak (Docker)

```bash
docker run -d \
  --name keycloak \
  -p 8080:8080 \
  -e KEYCLOAK_ADMIN=admin \
  -e KEYCLOAK_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:latest \
  start-dev
```

Access Keycloak at `http://localhost:8080`

### Edesy Email .env

```bash
# Authentication
AUTH_DRIVER=openid
AUTH_OPENID_NAME=Login with Keycloak
AUTH_OPENID_ISSUER_URL=http://localhost:8080/realms/master
AUTH_OPENID_CLIENT_ID=edesy-email
AUTH_OPENID_CLIENT_SECRET=your-secret-here
AUTH_OPENID_DOMAIN=

# Base URLs
BASE_URL=http://localhost:3000
API_BASE_URL=http://localhost:3000/api

# Other required settings
APP_SECRET=your-app-secret-here
DB_HOST=localhost
DB_USERNAME=edesy-email
DB_PASSWORD=password
DB_PORT=3306
DB_DATABASE=edesy-email
REDIS_HOST=localhost
REDIS_PORT=6379
```

## Migration from Basic Auth

If you're currently using basic auth and want to migrate to Keycloak:

1. **Set up Keycloak** as described above
2. **Create your admin user** in Keycloak with the same email
3. **Update environment variables** to use OpenID
4. **Test the login** before fully switching
5. **Keep basic auth as backup** during transition:
   ```bash
   AUTH_DRIVER=openid,basic
   ```
6. **Remove basic auth** once you confirm Keycloak works:
   ```bash
   AUTH_DRIVER=openid
   ```

## Additional Resources

- [Keycloak Documentation](https://www.keycloak.org/documentation)
- [OpenID Connect Specification](https://openid.net/connect/)
- [Edesy Email Authentication Docs](https://edesy.in/docs/email-platform/advanced/authentication)

## Support

If you encounter issues:
1. Check the Edesy Email logs for error details
2. Check Keycloak admin console -> Events for authentication events
3. Verify your configuration matches this guide
4. Open an issue on the Edesy Email GitHub repository
