Інтеграція Active Directory / LDAP для корпоративного мобільного додатку
Прямо LDAP-інтеграція в мобільному додатку — це майже завжди архітектурна помилка. Мобільний клієнт не повинен з'єднуватися з LDAP-сервером напряму: порти 389/636 закриті за корпоративним файрволом, LDAP-bind credentials неможливо зберігати на пристрої, з'єднання через мобільний інтернет до on-premise AD — нестабільне. Правильна схема: мобільний → backend API → AD/LDAP.
Архітектура інтеграції
Backend виступає LDAP-прокси: приймає запити від мобільного через HTTPS з JWT-авторизацією, звертається до AD/LDAP всередині корпоративної мережі, повертає дані у REST-форматі.
Мобільний ──HTTPS/JWT──► Backend API ──LDAP 636──► Active Directory
└──LDAP 389──► OpenLDAP
Для аутентифікації через AD на backend використовуємо 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();
}
});
});
}
Після успішного bind backend генерує JWT та повертає на мобільний. Пароль користувача ніколи не покидає backend.
Отримання атрибутів користувача
AD зберігає багатий набір атрибутів: displayName, mail, telephoneNumber, department, manager, memberOf (групи), thumbnailPhoto (аватар). Для корпоративного додатку це цінне джерело даних — не потрібно дублювати профілі користувачів.
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 — JPEG в base64 прямо в AD. Повертаємо як base64-строку або зберігаємо у object storage та повертаємо URL.
memberOf містить DN групп: CN=VPN-Users,OU=Groups,DC=company,DC=local. Групи визначають права користувача в додатку — парсимо CN з DN та маппимо на application roles.
Робота з оргструктурою
AD містить ієрархію через атрибут manager (DN керівника) та directReports. Побудувати дерево оргструктури через рекурсивні LDAP-запити — можливо, але повільно при глибоких ієрархіях. Краще: кешувати структуру на backend з періодичним оновленням (раз на годину/день), мобільний запитує готовий граф.
// Android — відображення оргструктури
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)
// Рекурсивно для вложених рівнів через expandable state
}
}
}
Пошук сотрудників
Повнотекстовий пошук по AD через LDAP-фільтр:
const filter = `(&(objectClass=person)(|(displayName=*${query}*)(mail=*${query}*)(sAMAccountName=*${query}*)))`;
Продуктивність: wildcard на початку (*${query}*) не використовує індекс AD, пошук повільний при великій базі. Для додатків з тисячами працівників — синхронізуємо AD в Elasticsearch або PostgreSQL full-text search, пошук там.
Синхронізація та кеш
AD — джерело правди для даних про працівників. Мобільний додаток працює з кешем backend. Для актуальності: webhook-события через AD Event Log (якщо AD 2016+) або polling раз на 15–30 хвилин на зміни через атрибут uSNChanged.
При звільненні сотрудника аккаунт в AD деактивується. Backend при наступному refresh_token бачить failed LDAP lookup та інвалідирує JWT. Мобільний переспрямовується на логін.
Особливості Azure AD (Entra ID)
Якщо компанія використовує Azure AD (Microsoft Entra ID) — прямого LDAP немає, тільки Microsoft Graph API або OIDC. Graph API набагато зручніше: REST, JSON, багата документація. GET /users/{id}?$select=displayName,mail,department,manager,memberOf повертає все те ж, що й LDAP, але без AD-бібліотек.
Для гібридного середовища (on-premise AD + Azure AD з Azure AD Connect) — дані синхронізуються, можна використовувати либо Graph API, либо on-premise LDAP в залежності від вимог безпеки.
Інтеграція AD/LDAP (backend-прокси + мобільний клієнт + оргструктура + пошук): 3–6 тижнів. Вартість розраховується індивідуально після аналізу інфраструктури замовника.







