208 lines
5.6 KiB
Markdown
208 lines
5.6 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
git clone https://your-gitea-instance.com/ldap-to-oauth2.git
|
|
cd ldap-to-oauth2
|
|
```
|
|
|
|
### 2. Install dependencies
|
|
|
|
```bash
|
|
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:
|
|
|
|
```javascript
|
|
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
|
|
|
|
```bash
|
|
node server.js
|
|
```
|
|
|
|
## Testing
|
|
|
|
Test authentication using `ldapsearch`:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
echo 'ldap_oauth_bridge_enable="YES"' >> /etc/rc.conf
|
|
service ldap_oauth_bridge start
|
|
```
|
|
|
|
### 3. Check service status
|
|
|
|
```bash
|
|
service ldap_oauth_bridge status
|
|
sockstat -l | grep 3893
|
|
```
|
|
|
|
## Configuration Examples
|
|
|
|
### TheLounge IRC Client
|
|
|
|
In `config.js`:
|
|
|
|
```javascript
|
|
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=com` → `alice`)
|
|
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:
|
|
|
|
```bash
|
|
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
|
|
|
|
- Built with [ldapjs](https://github.com/ldapjs/node-ldapjs)
|
|
- OAuth2 requests powered by [axios](https://github.com/axios/axios)
|