Direct LDAP integration in a mobile app is almost always an architectural mistake: ports 389/636 are blocked by firewalls, LDAP bind credentials can't be stored on the device, and the connection via mobile internet to on-premise AD is unstable. The correct scheme is a backend proxy: mobile → backend API → AD/LDAP. This ensures security and scalability. We implement turnkey integration using modern protocols and encryption. Our certified engineers conduct an infrastructure audit and offer the optimal solution. Leave a request for a free consultation to assess your project.
Why You Should Not Connect to LDAP Directly from Mobile
Mobile networks are unpredictable, and corporate LDAP servers sit behind strict firewalls. Attempting a direct connection leads to network blocks, requirements to open ports (violating security policies), and the vulnerability of storing credentials on the device. Even with a VPN, this adds latency and management complexity. A backend proxy solves these problems: all connections originate from a secure network segment, and the mobile app communicates only over HTTPS with JWT.
Integration Architecture: Backend Proxy
The backend acts as an LDAP proxy: it accepts requests from the mobile over HTTPS with JWT authorization, queries AD/LDAP inside the corporate network, and returns data in REST format.
Mobile ──HTTPS/JWT──► Backend API ──LDAP 636──► Active Directory └──LDAP 389──► OpenLDAP For authentication via AD on the backend, we use LDAP bind:
// Node.js, ldapjs const client = ldap.createClient({ url: "ldaps://dc01.company.local:636", tlsOptions: { rejectUnauthorized: true, ca: [fs.readFileSync("ca.crt")] }, }); async function authenticateUser(username, password) { const userDN = `cn=${username},ou=Users,dc=company,dc=local`; return new Promise((resolve, reject) => { client.bind(userDN, password, (err) => { if (err) { reject(new InvalidCredentialsError()); } else { resolve(true); client.unbind(); } }); }); } After a successful bind, the backend generates a JWT and returns it to the mobile. The user's password never leaves the backend.
| Parameter | Direct Access | Backend Proxy |
|---|---|---|
| Security | Low: password on device | High: password not stored |
| Scalability | Limited: network stability | High: caching, load balancing |
| Speed | Depends on client network | Optimized on backend |
| Implementation complexity | Simple but risky | Requires development |
For a retail client with 5,000 employees, we implemented this architecture, reducing login time from 3 seconds to under 1 second and eliminating credential storage risks.
How to Protect User Credentials
The user's password is transmitted from the mobile to the backend over HTTPS. The backend performs an LDAP bind — the only place where the password is used. After authentication, the backend generates a JWT with a limited lifetime (e.g., 1 hour). The mobile device stores only the JWT; the password is never cached. When an employee leaves, their AD account is deactivated; the backend, on the next refresh_token, detects a failed LDAP lookup and invalidates the JWT — access is immediately blocked.
Fetching User Attributes
AD stores a rich set of attributes: displayName, mail, telephoneNumber, department, manager, memberOf (groups), thumbnailPhoto (avatar). For a corporate app, this is a valuable data source — no need to duplicate user profiles.
async function getUserAttributes(username) { const base = "ou=Users,dc=company,dc=local"; const opts = { filter: `(sAMAccountName=${username})`, scope: "sub", attributes: [ "displayName", "mail", "department", "manager", "memberOf", "thumbnailPhoto", ], }; return new Promise((resolve, reject) => { client.search(base, opts, (err, res) => { let entry = null; res.on("searchEntry", (e) => (entry = e.object)); res.on("end", () => resolve(entry)); res.on("error", reject); }); }); } thumbnailPhoto is JPEG in base64 directly in AD. We return it as a base64 string or save it in object storage and return a URL.
memberOf contains group DNs: CN=VPN-Users,OU=Groups,DC=company,DC=local. Groups determine user permissions in the app — we parse the CN from the DN and map to application roles.
Building the Organizational Structure from AD
AD provides hierarchy through the manager attribute (manager's DN) and directReports. Building an org tree via recursive LDAP queries is possible but slow for deep hierarchies. Better: cache the structure on the backend with periodic updates (once per hour/day), and the mobile requests the ready graph.
// Android — displaying org structure data class OrgNode( val employeeId: String, val name: String, val position: String, val department: String, val avatarUrl: String?, val directReports: List<OrgNode> ) @Composable fun OrgChart(rootNode: OrgNode) { LazyColumn { item { EmployeeCard(node = rootNode, level = 0) } items(rootNode.directReports) { report -> EmployeeCard(node = report, level = 1) // Recursive for nested levels via expandable state } } } Employee Search
Full-text search in AD via LDAP filter:
const filter = `(&(objectClass=person)(|(displayName=*${query}*)(mail=*${query}*)(sAMAccountName=*${query}*)))`; Performance: a leading wildcard (*${query}*) doesn't use the AD index; search is slow for large directories. For apps with thousands of employees, we sync AD to Elasticsearch or PostgreSQL full-text search and perform search there.
Caching and Synchronization
AD is the source of truth for employee data. The mobile app works with the backend cache. For freshness: webhook events via AD Event Log (AD 2016+) or polling every 15–30 minutes for changes via the uSNChanged attribute.
When an employee is terminated, the AD account is deactivated. The backend, on the next refresh_token, sees a failed LDAP lookup and invalidates the JWT. The mobile is redirected to login.
Azure AD (Entra ID) Specifics
If the company uses Azure AD (Microsoft Entra ID) — no direct LDAP, only Microsoft Graph API or OIDC. Graph API is much more convenient: REST, JSON, rich documentation. GET /users/{id}?$select=displayName,mail,department,manager,memberOf returns everything LDAP does, without ADO libraries.
For a hybrid environment (on-premise AD + Azure AD with Azure AD Connect) — data is synced; you can use either Graph API or on-premise LDAP depending on security requirements.
What's Included
- Audit of current AD/LDAP infrastructure and mobile app
- Design of backend-proxy architecture
- Implementation of authentication via LDAP bind with JWT
- API for attributes, org structure, and search
- Configuration of caching and synchronization
- Integration with Azure Graph API (if needed)
- Documentation and training for the client's team
- Technical support during operation
Estimated Timeline and Cost
Integration of AD/LDAP (backend proxy + mobile client + org structure + search): 3–6 weeks. Cost is determined after an initial assessment. Contact us for an audit to get an exact quote.
Our team has completed over 15 AD/LDAP integration projects for banks, retail, and industry. We guarantee compatibility with any LDAP server (OpenLDAP, FreeIPA, Active Directory). Contact us for an audit and receive an individual offer.







