# Admin SDK Users via Apps Script [[TOC]] ## Admin SDK inschakelen De Admin SDK is een Advanced Service die je handmatig moet activeren in je Apps Script project. Open je script via Extensies > Apps Script, klik in het linkermenu op Services (de plusknop) en schakel de "Admin SDK API" in. De service wordt dan beschikbaar als het globale object `AdminDirectory`. ```javascript function controleerActivering() { try { AdminDirectory.Users.list({ domain: 'bedrijf.nl', maxResults: 1 }); Logger.log('Admin SDK actief'); } catch (e) { Logger.log('Activeer Admin SDK in Services: ' + e.message); } } ``` Het script moet worden uitgevoerd door een gebruiker met superbeheerdersrechten, of door een beheerdersrol met de rechten voor gebruikersbeheer. Voor onbeheerde achtergrondtaken zonder ingelogde beheerder gebruik je een serviceaccount met domeinbrede delegatie. :::warn title="Beheer is krachtig en onomkeerbaar" Dit zijn beheerdersacties op je hele organisatie. Een fout in `update` of `remove` raakt echte accounts. Test eerst op een testdomein of een wegwerp-OU, en bouw een dry-run in waarbij je acties alleen logt voordat je ze echt uitvoert. ::: ## Gebruikers opvragen ```javascript function haalGebruikersOp() { const opties = { domain: 'bedrijf.nl', maxResults: 200, orderBy: 'familyName', projection: 'full', }; let pageToken; const alleGebruikers = []; do { if (pageToken) opties.pageToken = pageToken; const resultaat = AdminDirectory.Users.list(opties); if (resultaat.users) { alleGebruikers.push(...resultaat.users); } pageToken = resultaat.nextPageToken; } while (pageToken); Logger.log(`Totaal gebruikers: ${alleGebruikers.length}`); return alleGebruikers; } ``` :::warn title="Paginering is verplicht bij grote domeinen" Eén aanroep geeft maximaal `maxResults` gebruikers terug, met een harde bovengrens van 500 per aanroep. Laat je `maxResults` weg, dan cappt de API op 100. Loop daarom altijd door met `nextPageToken` tot die leeg is, anders mis je stilletjes gebruikers. ::: ## Gebruikers aanmaken Een nieuw account vereist een wachtwoord van 8 tot 100 tekens. De Directory API accepteert ofwel platte tekst, ofwel een hash met het bijbehorende `hashFunction`-veld. Als je een hash meestuurt, moet die hexadecimaal (base16) gecodeerd zijn, niet base64. Voor de meeste scripts is platte tekst in combinatie met `changePasswordAtNextLogin` eenvoudiger en minder foutgevoelig. ```javascript function maakGebruikerAan() { const nieuweGebruiker = { primaryEmail: 'jan.smit@bedrijf.nl', name: { givenName: 'Jan', familyName: 'Smit', }, password: Utilities.getUuid(), changePasswordAtNextLogin: true, orgUnitPath: '/Medewerkers/Sales', }; const aangemaakt = AdminDirectory.Users.insert(nieuweGebruiker); Logger.log(`Aangemaakt: ${aangemaakt.primaryEmail} (ID: ${aangemaakt.id})`); } ``` `Utilities.getUuid()` levert een willekeurig, lang wachtwoord dat de gebruiker bij de eerste login meteen vervangt. Wil je toch een hash sturen, gebruik dan een hexadecimale codering, bijvoorbeeld een SHA-1-hash via `Utilities.computeDigest(...)` die je zelf naar hex omzet, met `hashFunction: 'SHA-1'`. :::tip title="Stuur wachtwoorden nooit terug via e-mail" Een tijdelijk wachtwoord in een gewone e-mail is een lek. Forceer `changePasswordAtNextLogin: true` en deel het wachtwoord via een veilig kanaal, of laat de gebruiker zelf een reset doen via je helpdeskproces. ::: ## Gebruikers bijwerken ```javascript function bijwerkenGebruiker() { const email = 'jan.smit@bedrijf.nl'; AdminDirectory.Users.update({ name: { givenName: 'Johannes', familyName: 'de Smit', }, orgUnitPath: '/Medewerkers/Management', }, email); } ``` `update` werkt als een gedeeltelijke wijziging: alleen de velden die je meestuurt veranderen, de rest blijft staan. Wil je een account opschorten of weer activeren, dan zet je los het veld `suspended`: ```javascript function schortOp(email) { AdminDirectory.Users.update({ suspended: true }, email); } function activeer(email) { AdminDirectory.Users.update({ suspended: false }, email); } ``` ## Wachtwoord resetten ```javascript function resetWachtwoord(email) { const nieuwWachtwoord = Utilities.getUuid(); AdminDirectory.Users.update({ password: nieuwWachtwoord, changePasswordAtNextLogin: true, }, email); Logger.log(`Wachtwoord gereset voor ${email}, gebruiker moet bij eerste login wijzigen`); } ``` Deel het nieuwe wachtwoord niet in platte tekst per e-mail. Beter is een veilig kanaal of een proces waarbij de beheerder de gebruiker mondeling of via een wachtwoordkluis informeert. ## Aliassen beheren ```javascript function beheerAliassen() { const email = 'jan.smit@bedrijf.nl'; AdminDirectory.Users.Aliases.insert({ alias: 'j.smit@bedrijf.nl', }, email); const aliassen = AdminDirectory.Users.Aliases.list(email); if (aliassen.aliases) { aliassen.aliases.forEach(a => Logger.log(a.alias)); } AdminDirectory.Users.Aliases.remove(email, 'oud.alias@bedrijf.nl'); } ``` ## Bulk gebruikersbeheer vanuit een spreadsheet Een veelvoorkomende workflow is het aanmaken van veel accounts vanuit een sheet met kolommen als Voornaam, Achternaam, E-mail, Organisatie-eenheid en Status. De kolom Status voorkomt dubbel aanmaken bij een herstart. ```javascript function bulkAanmaakVanuitSheet() { const blad = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Nieuwe gebruikers'); const data = blad.getDataRange().getValues(); const headers = data[0]; const voornaamIdx = headers.indexOf('Voornaam'); const achternaamIdx = headers.indexOf('Achternaam'); const emailIdx = headers.indexOf('E-mail'); const ouIdx = headers.indexOf('Organisatie-eenheid'); const statusIdx = headers.indexOf('Status'); for (let i = 1; i < data.length; i++) { if (data[i][statusIdx] === 'Aangemaakt') continue; try { AdminDirectory.Users.insert({ primaryEmail: data[i][emailIdx], name: { givenName: data[i][voornaamIdx], familyName: data[i][achternaamIdx], }, password: Utilities.getUuid(), changePasswordAtNextLogin: true, orgUnitPath: data[i][ouIdx] || '/Medewerkers', }); blad.getRange(i + 1, statusIdx + 1).setValue('Aangemaakt'); Utilities.sleep(150); } catch (e) { blad.getRange(i + 1, statusIdx + 1).setValue('Fout: ' + e.message); } } } ``` De `Utilities.sleep(150)` houdt je onder de snelheidslimiet van de Admin SDK en voorkomt `rateLimitExceeded`-fouten bij grote batches. Geef elke gebruiker een uniek, willekeurig startwachtwoord in plaats van één gedeeld wachtwoord voor de hele lijst. :::howto title="Offboarding-workflow automatiseren" 1. Trigger de functie vanuit een HR-formulier of voer hem handmatig uit. 2. Haal het gebruikersobject op met `AdminDirectory.Users.get(email)`. 3. Draag eigenaarschap van belangrijke Drive-bestanden over naar de manager. 4. Verwijder de gebruiker uit alle groepen met `AdminDirectory.Members.delete()`. 5. Schort het account op met `AdminDirectory.Users.update({ suspended: true }, email)`. 6. Plan eventuele permanente verwijdering via een time-based trigger, met `AdminDirectory.Users.remove(email)`. 7. Stuur een bevestiging naar HR. ::: Houd er rekening mee dat een verwijderde gebruiker in Workspace nog 20 dagen herstelbaar is. Daarna is het account en de bijbehorende data definitief weg, dus plan permanente verwijdering bewust en niet te snel. :::faq ### Welke rechten heb ik nodig voor de Admin SDK? Je moet superbeheerder zijn of een aangepaste beheerdersrol hebben met de rechten voor gebruikersbeheer. Voor onbeheerde scripts zonder ingelogde beheerder gebruik je een serviceaccount met domeinbrede delegatie en de juiste OAuth-scopes. ### Hoeveel gebruikers krijg ik per aanroep terug? Maximaal 500 per aanroep, en standaard 100 als je `maxResults` weglaat. Gebruik altijd `nextPageToken` om door alle pagina's te lopen, anders mis je gebruikers in grotere domeinen. ### Kan ik gebruikers permanent verwijderen? `AdminDirectory.Users.remove(email)` verwijdert een gebruiker. In Workspace blijft het account daarna nog 20 dagen herstelbaar via het beheerdersconsole. Voor een tijdelijke deactivatie gebruik je `suspended: true`, dat is omkeerbaar. ### Hoe stel ik een wachtwoord veilig in? Stuur een lang, willekeurig wachtwoord, bijvoorbeeld via `Utilities.getUuid()`, samen met `changePasswordAtNextLogin: true`. Stuur je een hash, codeer die dan hexadecimaal (base16) en zet het juiste `hashFunction`. Een base64-hash wordt door de API niet correct verwerkt. ### Hoe voeg ik aangepaste attributen toe aan gebruikers? Definieer eerst een custom schema via de Schemas-resource van de API. Daarna kun je het object `customSchemas` meesturen in het gebruikersobject bij `insert` of `update`. ### Hoe voorkom ik snelheidsfouten bij bulk-acties? Bouw een korte pauze in tussen aanroepen, bijvoorbeeld `Utilities.sleep(150)`, en vang fouten per rij af zodat één mislukte gebruiker de hele batch niet stopt. Schrijf de uitkomst per rij terug naar je sheet voor een audittrail. ::: De Admin SDK Users service is het fundament van geautomatiseerd gebruikersbeheer in Google Workspace. Combineer het met de Groups service voor volledig lifecyclebeheer van medewerkers, van onboarding tot offboarding.