2025-10-08 11:12:59 -04:00
2025-10-08 11:12:59 -04:00
2025-10-08 11:12:59 -04:00
2025-10-08 11:12:59 -04:00
2025-10-08 11:12:59 -04:00
2025-10-08 11:12:59 -04:00

LDAP to OAuth2 Bridge

A lightweight LDAP server that authenticates users against an OAuth2/OIDC provider (such as Keycloak). This bridge allows legacy applications that only support LDAP authentication to work with modern OAuth2 identity providers.

Overview

This bridge presents an LDAP interface to applications while performing OAuth2 Resource Owner Password Credentials (ROPC) flow authentication against your identity provider in the background.

Use Case: Integrate applications like TheLounge IRC client, which only support LDAP authentication, with Keycloak or other OAuth2/OIDC providers.

Features

  • Lightweight Node.js implementation
  • Simple LDAP bind operation support
  • OAuth2 Resource Owner Password Credentials flow
  • Configurable base DN
  • Easy integration with Keycloak and other OIDC providers
  • FreeBSD service support (includes rc.d script)

Requirements

  • Node.js 14+ and npm
  • An OAuth2/OIDC provider (Keycloak, Auth0, etc.)
  • A client configured with Direct Access Grants enabled

Installation

1. Clone the repository

git clone https://your-gitea-instance.com/ldap-to-oauth2.git
cd ldap-to-oauth2

2. Install dependencies

npm install

3. Configure OAuth2 Provider

For Keycloak:

  1. Create a new client in your realm
  2. Set Access Type to confidential
  3. Enable Direct Access Grants Enabled
  4. Save and retrieve the client secret from the Credentials tab

For other providers:

Ensure your OAuth2 provider supports the Resource Owner Password Credentials grant type.

4. Configure the bridge

Edit server.js and update the configuration section:

const LDAP_PORT = 3893;
const KEYCLOAK_URL = 'https://your-keycloak-domain.com';
const KEYCLOAK_REALM = 'your-realm';
const KEYCLOAK_CLIENT_ID = 'your-client-id';
const KEYCLOAK_CLIENT_SECRET = 'your-client-secret';
const BASE_DN = 'dc=example,dc=com';

5. Run the server

node server.js

Testing

Test authentication using ldapsearch:

ldapsearch -H ldap://localhost:3893 \
  -D "cn=username,dc=example,dc=com" \
  -W \
  -b "dc=example,dc=com"

Replace username with a valid username from your OAuth2 provider.

FreeBSD Service Installation

1. Copy files to system directories

# Copy application files
cp -r ldap-to-oauth2 /usr/local/ldap-oauth-bridge

# Copy RC script
cp ldap_oauth_bridge.rc /usr/local/etc/rc.d/ldap_oauth_bridge
chmod +x /usr/local/etc/rc.d/ldap_oauth_bridge

2. Enable and start service

echo 'ldap_oauth_bridge_enable="YES"' >> /etc/rc.conf
service ldap_oauth_bridge start

3. Check service status

service ldap_oauth_bridge status
sockstat -l | grep 3893

Configuration Examples

TheLounge IRC Client

In config.js:

ldap: {
    enable: true,
    url: "ldap://your-server:3893",
    baseDN: "dc=example,dc=com",
    searchDN: {
        rootDN: "cn=admin,dc=example,dc=com",
        rootPassword: "dummy",
        filter: "(|(uid=%s)(cn=%s))"
    }
}

Generic LDAP Application

  • LDAP Server: ldap://your-server:3893
  • Base DN: dc=example,dc=com
  • Bind DN Format: cn=USERNAME,dc=example,dc=com

Users authenticate with their OAuth2 provider username and password.

How It Works

  1. Application sends LDAP BIND request with username and password
  2. Bridge extracts username from the LDAP DN (e.g., cn=alice,dc=example,dc=comalice)
  3. Bridge performs OAuth2 password grant flow with the identity provider
  4. If OAuth2 authentication succeeds, LDAP BIND succeeds
  5. If OAuth2 authentication fails, LDAP BIND fails

Security Considerations

  • Transport Security: Use LDAPS (LDAP over TLS) in production or ensure the bridge runs on a trusted network
  • Port < 1024: Requires root privileges on Unix systems. Consider using port 3893 or higher to avoid running as root
  • Password Grant Flow: The Resource Owner Password Credentials flow passes passwords to the bridge. Ensure secure communication channels
  • Network Isolation: Run the bridge on the same network as your applications or use VPN/tunneling

Limitations

  • Only supports LDAP BIND operations (authentication only)
  • Does not provide a full LDAP directory (no user enumeration, group queries, etc.)
  • Search operations return empty results
  • Requires OAuth2 provider to support Resource Owner Password Credentials grant

Troubleshooting

Authentication fails

  1. Check server logs for detailed error messages
  2. Verify OAuth2 client credentials are correct
  3. Ensure Direct Access Grants are enabled in your OAuth2 client
  4. Test OAuth2 authentication directly using curl:
curl -X POST https://your-keycloak/realms/your-realm/protocol/openid-connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=password" \
  -d "client_id=your-client-id" \
  -d "client_secret=your-client-secret" \
  -d "username=testuser" \
  -d "password=testpass"

Connection refused

  • Verify the server is running: sockstat -l | grep 3893
  • Check firewall rules
  • Ensure the application can reach the bridge server

DN parsing errors

  • Ensure username is formatted as cn=username,dc=example,dc=com or uid=username,dc=example,dc=com
  • Check server logs for DN parsing details

License

MIT License - See LICENSE file for details

Contributing

Contributions are welcome! Please submit pull requests or open issues on the repository.

Author

Created for use with TheLounge IRC client and Keycloak authentication.

Acknowledgments

Description
No description provided
Readme 1 MiB
Languages
JavaScript 100%