Als echte software developers willen we natuurlijk ons vakmanschap tonen en goede producten afleveren. Een echte vakman in 1950, zoals een timmerman, maakte voor elke deur een tekening en ging dan met de hand het hout te pas maken. Inmiddels doen we dat anders. Want hoe mooi we een handgemaakte deur ook vinden, we willen liever dat onze deuren veilig zijn tegen inbraak en dat ze niet rammelen of klemmen. Dus worden ze tegenwoordig in een standaardproces gemaakt, zodat de kwaliteit constant is.
afbeelding 1
Zo kun je ook naar Identity and Access Management kijken. Het is mooi om zelf elke keer een op maat gemaakte oplossing te coderen, maar omdat de veiligheid dan in het geding kan komen, kunnen we beter kiezen voor een standaard oplossing met een constante kwaliteit.
Wat is Identity and Access Management (IAM)?
Alles begint bij Identification. De computer wil weten wie je bent. Dan komt de Authentication. Kun je bewijzen dat je die persoon ook echt bent? En daarnaast heb je te maken met Authorization. Wat mag je doen in dit systeem?
Als je dit met de hand wilt gaan programmeren, dan maak je eerst eenvoudig een gebruikerstabel met wachtwoorden. Maar als je database buit gemaakt wordt tijdens een hack, wil je je wachtwoorden wel versleuteld hebben. Dus is het noodzakelijk dat je nadenkt over hashing en welke hashing algoritmes je gaat gebruiken. Vergeet ook salting niet. En welk wachtwoordbeleid ga je instellen?
Naast deze basiselementen komt er nog meer kijken. Je hebt nodig:
- een wachtwoord vergeten/ wachtwoord opnieuw instellen functie;
- account aanmaken;
- account updaten;
- dat je rollen kunt toekennen met bijbehorende toegestane acties.
Het bouwen van al deze elementen is de eerste keer leuk, maar als je het voor de vijfde keer moet maken voor weer een ander product, dan wordt het saai. En als je saaie werkzaamheden doet, maak je meer fouten. Een groot risico voor de veiligheid.
IAM en open source
In open source werken mensen samen die allemaal belang erbij hebben dat het product van topkwaliteit is. Die samenwerking, en het feit dat de code vrij toegankelijk is, zorgt ervoor dat mensen elkaars blinde vlekken aan het licht brengen en zo zorgen voor een beter resultaat. Zeker in deze tijd van steeds complexere toegangsmethoden kunnen we van elkaars expertise profiteren. Want fouten in toegangsmanagement kunnen ertoe leiden dat gevoelige informatie op straat komt te liggen. En klanten rekenen erop dat wij dat niet laten gebeuren.
Een recent voorbeeld van hoe dit verkeerd kan gaan is Ashley Madison, een online datingsite voor mensen die al een vaste relatie hebben. Dit haalde alle kranten en journaals. Je kunt je voorstellen dat deze site een schat aan informatie herbergt, die de gebruikers graag privé willen houden. Emailadressen, namen, huisadressen, creditcardgegevens en wachtwoorden. Het spreekt voor zich dat de makers van deze site echt hun huiswerk hebben gedaan om deze gegevens zo goed mogelijk te beschermen. Hiervoor zijn de 36 miljoen wachtwoorden in de vorm van bcrypt hashes opgeslagen.
Toen hackers toesloegen, vonden ze echter een bug in de bcrypt van Madison. Daardoor hadden ze niet slechts de 4.000 zwakke wachtwoorden te pakken, maar konden ze in slechts tien dagen elf miljoen wachtwoorden achterhalen. Ongetwijfeld hadden de gebruikers van deze site een betere bescherming van hun gegevens verwacht. Sensitive Data Exposure staat niet voor niets in de OWASP top 10.
afbeelding 2
OAuth 2.0
De twee meest gebruikte methodes voor IAM op het internet zijn OAuth & SAML. OAuth kent een lange workflow (zie afbeelding 2). Er zijn dus veel plekken waar je een klein foutje kan maken als codeschrijver. Vroeger was het nog wel te doen met enkelvoudige systemen in de klassieke architectuur. Maar nu, met de moderne structuren, zijn zaken als Access Management complex geworden. Hierdoor is het nog belangrijker geworden om eerst goed te kijken wat er al is voor je zelf een oplossing gaat ontwikkelen.
User federation
We kunnen eenvoudig de inlogmethodes inzetten die gebruikers al gewend zijn te gebruiken, zoals die van Facebook, Google+ en Twitter. Maar ook LDAP, Active Directory en zelfs de banken (Idin & Idensys). Deze diensten weten heel goed hoe ze de identiteit van gebruikers kunnen vaststellen.
Een voorbeeld van een open source project dat ons als software developers een product van constante kwaliteit in handen geeft, is Keycloak. Naast Keycloak zijn er nog andere open source projecten die met ons mee denken op het gebied van Identity and Access Management, zoals:
- Shibboleth, een Single Sign-On syteem gebaseerd op SAML;
- OpenAM, een open SSO systeem;
- CAS Server, een SSO server gebaseerd op het open CAS protocol.
Voorbeeld applicatie: kiteclub
De Kiteclub is een groep drone-eigenaren die de informatie over hun drones willen delen in een webapplicatie. Ze zetten Keycloak in om deze bestaande Java EE applicatie te beveiligen. Ik laat je stap voor stap zien hoe dit moet. In GitHub (zie refs) zijn deze stappen aangegeven met tags. Bij tag ‘step-0’ is de applicatie zonder enige beveiliging te vinden. Het geheel is als volgt gedeployed:
afbeelding 3
De installatie van Keycloak is kant-en-klaar: je hoeft alleen de zipfile uit te pakken. Het deployen van de Kiteclub applicatie vergt enige WildFly specifieke stappen, te vinden in de handleiding van Keycloak. In het kort komt het erop neer dat er een keycloak adapter wordt geïnstalleerd in WildFly. Voor andere servers, zoals bijv. Tomcat en ook Spring security, is ook een beschrijving beschikbaar.
Keycloak plaatst groepen applicaties en gebruikers in zogenaamde ‘Realms’. Zo kan één Keycloak-server gebruikt worden door verschillende domeinen, bijv. kantoorautomatisering en klanten. Je kunt eenvoudig een Realm maken en verschillende rollen toekennen aan verschillende deelnemers. Voor de Kiteclub-applicatie is een importbestand beschikbaar in GitHub. (keycloak-realm.json) Deze kan geüpload worden tijdens het aanmaken van een Realm in Keycloak.
afbeelding 4
Na het aanmaken, kan het koppel- en installatiebestand keycloak.json verkregen worden vanaf de ‘Installation’-tab van de realm. Deze dient geplaatst te worden in de ‘WEB-INF’ van het war-project. Met de gegevens in dit bestand kan de adapter verbinding maken met de Keycloak-server.
JAAS in web.xml
Voor de eerste stap kun je tag ‘step-1’ nu uitchecken. Java EE applicaties kunnen beveiligd worden door hiervoor configuratie op te nemen in het bestand ‘web.xml’. Normaal gesproken is daarvoor de keuze uit BASIC AUTH en FORM, voor Keycloak komt daar de optie KEYCLOAK bij. Zie hier deze snippit uit web.xml:
<login-config>
<auth-method>KEYCLOAK</auth-method>
<realm-name>Kiteclub</realm-name>
</login-config>
Hiermee wordt de koppeling gelegd tussen de Java EE applicatie met de Keycloak-adapter. Door de regels na deze snippit (‘security-constraint’- & ‘security-role’-tags) worden de pagina’s ‘/my-kites.jsp’ & ‘/admin.jsp’ beveiligd op de standaard JAAS-manier. Wanneer nu één van deze pagina’s bezocht wordt (vanaf ‘/index.jsp’) dan zal de Keycloak-adapter je doorsturen naar Keycloak om in te loggen, geheel via het OAuth protocol.
REST Services
Het voorgaande beveiligt je gewone JSP-pagina’s, maar je REST-services zijn nog onbeschermd. Die kun je ook beveiligen met extra opties in web.xml, maar eleganter los je dit op in de Java-classes zelf. Hiertoe kan ‘step-2’ uit gecheckt worden. Wanneer de wijzigingen bekeken worden, zien we drie regels toegevoegd worden in de vorm van annotaties op de REST-methoden in de class KiteService: @RolesAllowed({ “Member” }) geeft aan dat alleen gebruikers met de rol ‘Member’ deze service mogen gebruiken.
Gebruiker details
Wanneer we als service meer van onze gebruiker willen tonen (bijv. een volledige naam), dan kunnen we in het OAuth token kijken. Hierin zitten alle gegevens waarvoor de gebruiker impliciet of expliciet zijn toestemming heeft gegeven. De volledige naam kan gelezen worden door deze uit het token te halen:
String fullName = Joiner.on(" ").join(token.getGivenName(), token.getFamilyName());
Dit staat in ‘step-3′. We willen natuurlijk ook zorgen dat gebruikers alleen informatie kunnen bewerken van hun eigen kites. Daartoe moet een ’employeeNumber’ uit Keycloak meegestuurd worden. Hiervoor zou het algemene UUID van de gebruiker ook mogelijk zijn, maar wanneer je bijvoorbeeld met een LDAP-server zou koppelen, dan krijg je te maken met willekeurige technische sleutels. Om dit te omzeilen en met begrijpelijke sleutels te koppelen, kun je per gebruiker vrije attributen toevoegen. Deze kunnen via de Keycloak API uitgelezen worden uit het token met de methode ‘getOtherClaims()’. Dit staat uitgeschreven in ‘step-4’.
Themes
Om de gebruiker een mooie ervaring te geven, kan per Realm een ander theme geconfigureerd worden. Er kan in vier categorieën een theme geselecteerd worden: login, account, email & admin. Vooral de login is natuurlijk van belang, omdat dit de voorkant van je applicatie is. In map ‘src/main/keycloak-theme/kiteclub/login’ staan alle gegevens om een simpel login-theme te maken. Deze gegevens kunnen geplaatst worden in Keycloak onder de map ‘standalone/configuration/themes’ waarna het theme geselecteerd kan worden binnen de Keycloak-admin-pages.
Account page
Ook het aanpassen van het wachtwoord kan allemaal vanuit de account-pages. Deze zijn bereikbaar vanuit de link ‘Account’ in de header van de Kiteclub-applicatie. Wanneer je de code volgt, kom je uit bij de methode ‘User.getAccountUrl(…)’. De Account-page laat de gebruiker ook kiezen voor One-Time-Password voor extra veiligheid.
LDAP/AD
In het bedrijfsleven kom je vaak een andere bron van identiteiten tegen. Bijvoorbeeld LDAP of Active Directory. Deze bronnen kunnen eenvoudig gekoppeld worden via ‘User Federation’. Om dit te demonstreren, hebben we een voorbeeld LDAP-server nodig met het first8.nl domein erin. In ‘step-5’ zit de voorbeelddata. Zie hieronder voor de setup van ApacheDS.
Eenvoudig een ApacheDS starten via docker (bold stukje zelf invullen):
docker run \
-e "DOMAIN_NAME=first8" \
-e "DOMAIN_SUFFIX=nl" \
--name apacheds -d -p 10389:10389 \
-v /path/to/first8.nl.ldif:/tmp/first8.nl.ldif:ro \
jjhughes57/apacheds-docker
Daarna kun je de first8.nl.ldif laden via:
docker exec -i -t apacheds bash
ldapmodify -c -a \
-f /tmp/first8.nl.ldif -h localhost -p 10389 \
-D "uid=admin,ou=system" -w secret
Je kunt dan Apache Directory Studio aansluiten op localhost:10389 met Bind DN/wachtwoord uid=admin,ou=system/secret.
Keycloak kan aangesloten worden op deze ApacheDS LDAP-server onder het kopje “User Federation”. Hier kiezen we voor “Add provider… | LDAP ”. Dan vullen we deze waarden in:
- Console display name (First8-LDAP);
- Edit mode (writable);
- Vender (Other);
- Connection URL (ldap://localhost:10389);
- User DN (ou=People,dc=first8,dc=nl);
- Bind DN (uid=admin,ou=system);
- Bind Credentials (secret).
De rest kan default blijven staan. Test de connectie door de knop achter de ‘Connection URL’ en de credentials met de knop achter de ‘Bind credentials’. Als dit allemaal klopt, kan gebruiker ‘joep’ nu inloggen (wachtwoord ‘secret’). Nu zie je ook de ‘Common name’ & ‘Surname’ in de kiteclub verschijnen. Wanneer je deze in LDAP aanpast en opnieuw inlogged in de kiteclub, dan is het geheel aangepast. Het opnieuw inloggen is nodig omdat OAuth-OpenConnect deze ‘Common name’ & ‘Surname’ in het JWT-token heeft gezet en dat token is een bepaalde tijd geldig. Binnen die tijd zal WildFly niet opnieuw contact leggen met Keycloak.
Ook een wachtwoord aanpassing in LDAP is mogelijk: verander het wachtwoord van joep in LDAP en log opnieuw in met joep. Je zult merken dat je het nieuwe wachtwoord nodig hebt.
Conclusie
Met Keycloak als oplossing voor Identity and Access Management hebben we een product in handen wat gemakkelijk in te zetten is en wat goede ondersteuning biedt voor alle facetten van moderne Identity and Access Management.
Referenties
- Keycloak: http://keycloak.jboss.org/
- OAuth: http://oauth.net/
- OAuth vs SAML: https://www.mutuallyhuman.com/blog/2013/05/09/choosing-an-sso-strategy-saml-vs-oauth2/
- JWT: https://jwt.io/ (RFC 7519)
- ApacheDS: https://directory.apache.org/apacheds/
- GitHub: https://github.com/First8/kiteclub
- Idin: http://www.betaalvereniging.nl/giraal-en-online-betalen/idin/
- Idensys: https://www.rijksoverheid.nl/onderwerpen/digitale-overheid/inhoud/digitale-veiligheid-en-identiteit/naar-1-standaard-voor-elektronische-identiteit