First commit
This commit is contained in:
207
README.md
Normal file
207
README.md
Normal file
@ -0,0 +1,207 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user