Gebruikersbeheer met de hand werkt prima voor een handvol mensen, maar zodra je organisatie groeit wil je provisioning automatiseren. De Admin SDK Directory API laat je gebruikers, groepen en organisatie-eenheden volledig programmatisch beheren. In Python is dat een kwestie van een service bouwen en de juiste methoden aanroepen.
In dit artikel automatiseer je de volledige levenscyclus van een gebruiker: aanmaken bij instroom, bijwerken bij een functiewijziging en uitschakelen bij vertrek.
Wat je vooraf nodig hebt
Installeer eerst de officiele clientbibliotheken:
pip install google-auth google-api-python-client
Je hebt verder nodig:
- Een service account in een Google Cloud-project met de Admin SDK API ingeschakeld.
- Domain-wide delegation voor dat service account, geautoriseerd door een super-beheerder in de Admin console.
- Een beheerdersaccount in je domein dat het script mag impersoneren.
Authenticatie met impersonation
De Admin SDK werkt namens een beheerder. Een service account met domain-wide delegation kan een beheerder impersoneren via with_subject.
from google.oauth2 import service_account
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/admin.directory.user']
creds = service_account.Credentials.from_service_account_file(
'/secrets/sa-key.json', scopes=SCOPES
).with_subject('beheerder@jouwdomein.nl')
service = build('admin', 'directory_v1', credentials=creds)
Beperk de scope en bewaar de sleutel veilig
De scope admin.directory.user geeft volledige controle over alle gebruikers in je domein. Bewaar de service-accountsleutel in een secret manager (niet in je repo), geef alleen de scopes die je echt nodig hebt en log elke wijziging die je script doorvoert, zodat je altijd een audittrail hebt.
Een gebruiker aanmaken
Voor een nieuwe gebruiker geef je minimaal een naam, een primair e-mailadres en een initieel wachtwoord mee.
nieuwe_gebruiker = {
'name': {'givenName': 'Jan', 'familyName': 'Jansen'},
'primaryEmail': 'jan.jansen@jouwdomein.nl',
'password': genereer_sterk_wachtwoord(),
'changePasswordAtNextLogin': True,
'orgUnitPath': '/Verkoop',
}
service.users().insert(body=nieuwe_gebruiker).execute()
Forceer een eigen wachtwoord bij eerste login
Zet changePasswordAtNextLogin op True zodat de gebruiker bij de eerste login een eigen wachtwoord kiest. Genereer het tijdelijke wachtwoord willekeurig en lang, en deel het via een veilig kanaal, nooit via gewone e-mail.
De levenscyclus automatiseren
Een typische HR-integratie dekt instroom, wijziging en uitstroom. Het patroon ziet er zo uit:
- Een nieuwe medewerker in het HR-systeem leidt tot
users().insert(). - Een functiewijziging leidt tot
users().update()met een nieuwe organisatie-eenheid (orgUnitPath) of nieuwe groepslidmaatschappen. - Bij vertrek zet je eerst
suspendedopTrue, zodat e-mail en bestanden behouden blijven voor overdracht. - Na de bewaartermijn volgt
users().delete()of een transfer van de data via de Data Transfer API.
Een gebruiker uitschakelen
Bij vertrek schakel je een account eerst uit in plaats van het direct te verwijderen. Zo blijven e-mail en bestanden beschikbaar voor overdracht.
service.users().update(
userKey='jan.jansen@jouwdomein.nl',
body={'suspended': True}
).execute()
Gebruikers ophalen en doorlopen
Voor synchronisatie wil je vaak alle gebruikers ophalen. Houd rekening met paginering: gebruik list_next() om automatisch de volgende pagina op te halen.
gebruikers = []
request = service.users().list(customer='my_customer', maxResults=200)
while request is not None:
response = request.execute()
gebruikers.extend(response.get('users', []))
request = service.users().list_next(request, response)
my_customer is een handige alias
De waarde my_customer verwijst naar het account van de geauthenticeerde beheerder. Je hoeft je echte customer-ID dus niet hard te coderen.
Omgaan met rate limits
De Directory API kent quota per project. Bij grootschalige synchronisaties loop je tegen 403 rateLimitExceeded of 429-fouten aan. Vang deze op met een exponentiele backoff en bundel waar mogelijk meerdere bewerkingen.
Robuust schrijven naar de Directory API
- Vang
HttpErroraf en leeserror.resp.statusuit. - Bij status
403of429: wacht en probeer opnieuw met een oplopende wachttijd (bijvoorbeeld 1, 2, 4, 8 seconden) plus wat willekeurige jitter. - Gebruik batch-requests om meerdere
insert- ofupdate-calls te bundelen. - Log mislukte bewerkingen apart zodat je ze later gericht opnieuw kunt draaien.
Veelgestelde vragen
Waarom krijg ik een 403 ondanks correcte scopes?
Vaak ontbreekt de domain-wide delegation in de Admin console, of het geimpersoneerde account is geen beheerder. Controleer of de client-ID van het service account met exact deze scopes is geautoriseerd, en of het account uit with_subject superbeheerder- of voldoende rechten heeft.
Kan ik een gebruiker direct verwijderen?
Ja, met users().delete(), maar dat is onomkeerbaar. Schakel het account eerst uit met suspended=True en regel dataoverdracht voordat je verwijdert.
Hoe ken ik een gebruiker aan een organisatie-eenheid toe?
Zet het veld orgUnitPath in de body bij insert of update, bijvoorbeeld op /Verkoop. De OU moet al bestaan in je domein.
Kan ik meerdere gebruikers in een keer aanmaken?
Niet in een enkele call. Wel kun je batch-requests gebruiken om meerdere inserts efficient te bundelen, met backoff tegen rate limits.
Welke scope heb ik minimaal nodig?
Voor alleen-lezen synchronisatie volstaat admin.directory.user.readonly. Voor aanmaken, wijzigen en uitschakelen heb je de volledige scope admin.directory.user nodig.
Met de Admin SDK in Python automatiseer je gebruikersbeheer betrouwbaar en houd je je directory synchroon met je bronsystemen.