Security by design: authenticatie

Geschreven door Rob Dekkers

In de vorige blog Security by design: architectuur Mendix hebben wij de architectuur van een Mendix app beschreven. In deze blog zullen we meer details van de authenticatie, het inloggen, van Mendix bespreken en handvatten geven voor veilige inlogmechanismen. Het inloggen is de voordeur naar de applicatie en het belangrijkste mechanisme om onbevoegden buiten te houden. Eenmaal ingelogd, kun je de functionaliteit van de app gebruiken (volgens de toegekende rechten), maar ook gebruik maken van de client API en schermen en validaties omzeilen.

Wat is inloggen?

Inloggen of authenticatie is een handeling waarbij wordt gecontroleerd of een gebruiker is die hij beweert dat hij is door een opgegeven bewijs te controleren op echtheid. Standaard hanteert Mendix een usernaam en wachtwoord voor zogenaamde named users (users met een account in de app) als enige mogelijke vorm van authenticatie. Er is een zeer beperkt wachtwoordbeleid. Zaken als definitieve blokkade, wachtwoordexpiratie, geen gebruik maken van oude wachtwoorden, uitnodigen van gebruikers, uitdelen van wachtwoorden of vergeten wachtwoorden zijn niet standaard beschikbaar en moeten zelf worden ontwikkeld, eventueel met behulp van modules uit de appstore. Mendix kent ook single sign-on (SSO), maar dat laten we hier buiten beschouwing.

Indien het inloggen slaagt, dan krijgt de browser van de gebruiker een session cookie uitgereikt met daarin een tijdelijk sessionid. Met dit sessionid kan de browser steeds opnieuw communiceren met de runtime server zonder dat de gebruikersidentiteit opnieuw moet worden vastgesteld. Vervolgens wordt de browser verwezen naar een indexpagina die de Mendix client in de browser laadt met als eerste pagina de home page van de gebruiker. Vanaf het moment dat de mendix client in de browser is geladen, is de client API voor de gebruiker beschikbaar en heeft de gebruiker dus de mogelijkheid om ook buiten de schermen om met de runtime server te communiceren. Dit is belangrijk om zich te realiseren als er oplossingen voor inloggen worden ontwikkeld.

2FA

De algemene opvatting van beveiligingsexperts is dat het gebruik van username en wachtwoord alleen, in een internet-omgeving, niet veilig genoeg is en er minimaal een tweede mechanisme aan moet worden toegevoegd, de zogenaamde Two Factor Authentication (2FA). Dit principe is gebaseerd op een onderscheid in iets dat je weet (wachtwoord, pincode, BSN, antwoorden op geheime vragen) en iets dat je hebt (credit card, mobiele telefoon, hardware token) en eventueel ook iets dat je bent (vingerafdruk, irisscan, stemgeluid).
De meest voorkomende 2FA-mechanismen maken gebruik van de mobiele telefoon: het ingeven van een extra code via SMS, het scannen van een QR-code of een speciale authenticator app die gebaseerd op een shared secret tokens per tijdseenheid genereert. Daarbij geven experts aan dat SMS weer niet zo veilig is (en kost ook geld om te versturen).
Er zijn modules in de appstore om de tokens van verschillende tokengeneratoren (bijv. Google Authenticator) te controleren.

Andere gebruikers

Naast de named users van een webapplicatie of mobiele app zijn er ook andere gebruikers die toegang tot de app kunnen krijgen:

Anonieme gebruikers
Anonieme gebruikers zijn “normale” gebruikers, maar hebben geen account in de app. Een unieke usernaam wordt door Mendix gegenereerd en er wordt zonder wachtwoord ingelogd. Het is verstandig om de autorisatie van anonieme gebruikers zeer beperkt te houden of zelfs geen anonieme gebruikers toe te staan. Indien een anonieme gebruiker toegang wil krijgen tot onderdelen van de app waarvoor hij geen rechten heeft, dan moet hij inloggen en wordt er een inlogscherm getoond. 

Webservicegebruikers
Webservicegebruikers hebben een account en kunnen in de aanroep van de published service een usernaam en wachtwoord meegeven. Maar een webservice kan ook geconfigureerd worden dat een mircroflow de controles uitvoert en de usernaam bepaalt. Webservicegebruikers worden ook ingelogd en krijgen een session voor zolang de uitvoering van de webservice duurt. Maar een sessionid wordt niet bekend gemaakt, zodat een webservicegebruiker de webapplicatie niet kan benaderen.

Administrator
De administrator is een speciale user zonder account, maar logt in als normale user. Het wachtwoord is vastgelegd in de Mendix portal.

Aanroeper request handler
Aanroepers van request handlers hoeven niet in te loggen. De implementatie van de service in custom Java code bepaalt wat de eventuele eisen van authenticatie zijn.

Implementeren 2FA en wachtwoordbeleid

Implementatie van 2FA en een wachtwoordbeleid kan op verschillende manieren. Hieronder worden enkele scenario’s geschetst. Niet elke oplossing is even veilig. We gaan uit van het gebruik van een tokengenerator op een mobiele telefoon.

Ontwikkeld in de app
Een eerste mogelijkheid is om de 2FA te ontwikkelen in Mendix pagina’s. Direct na inloggen wordt via de home page de tweede factor gevraagd en pas als die stap succesvol is doorlopen, dan worden de schermen van de app beschikbaar voor de gebruiker, anders wordt de gebruiker uitgelogd. Ook kan op deze wijze een specifiek wachtwoordbeleid worden geïmplementeerd. De ontwikkeling kan volledig in Mendix plaatsvinden.

Het grote nadeel van dit scenario is dat de gebruiker na succesvol inloggen in de app (op basis van usernaam en wachtwoord) een Mendix client in de browser geladen krijgt en daarmee alle mogelijkheden heeft om via de client API de data en business logic van de app te benaderen. De gebruiker is namelijk al ingelogd op de applicatie.

Een verbetering die een 2FA-module uit de appstore geeft, is om de standaard inlogfunctie van Mendix te overrulen (registreren LoginActionListener met custom Java code via de runtime API) en vervolgens als anonieme gebruiker in te loggen. De rechten van de anonieme gebruiker kunnen dan zeer beperkt gemaakt worden voor alleen het gebruik van de inlogpagina’s. Na succesvolle controle van de tweede factor, wordt de gebruiker door de app via de runtime API ingelogd.

Ontwikkeld in de inlogpagina met gebruik van services
Een tweede mogelijkheid is om de inlogpagina aan te passen en daarin ook het 2FA-token op te vragen. Alvorens het inlogform naar de runtime server wordt gesubmit, wordt via een Ajax-call een published webservice aangeroepen die het 2FA-token bij de gebruiker vastlegt. Daarna wordt ingelogd door Mendix met username en wachtwoord. In de home page wordt het vastgelegde 2FA-token gecontroleerd. Indien de controle succesvol is, dan wordt vastgelegd dat de sessie van de gebruiker is geauthenticeerd, zodat bij het passeren van de home page niet opnieuw op het 2FA-token gecontroleerd zal worden. Als de controle faalt, dan wordt de gebruiker meteen uitgelogd.

Het grote voordeel van dit scenario is dat een gebruiker alleen een Mendix client in de browser geladen krijgt, als die door Mendix succesvol is ingelogd plus de verificatie van de 2FA is gelukt. Ook is er geen custom Java code voor nodig.

Het nadeel is dat er informatie bijgehouden moeten worden over sessies en dat dit ook weer moet worden opgeruimd na het verlopen van sessies. Wij hebben dit in eerste instantie op deze wijze voor een app geïmplementeerd, maar vonden de oplossing niet zo elegant, hoewel hij functioneel prima werkt.

Ontwikkeld in de inlogpagina met een custom Java login
Een derde mogelijkheid, die wij zelf toepassen, is om de inlogpagina uit te breiden met het 2FA-token en de login listener te overrulen met custom Java code. De login listener kent alleen usernaam en wachtwoord als parameters, maar het 2FA-token kan als http header worden meegegeven aan het request naar de runtime server. In de nieuwe login listener wordt een microflow aangeroepen die de usernaam/wachtwoordcombinatie en het 2FA-token controleert. Er wordt alleen ingelogd als de controle succesvol is. Er is verder geen impact op de applicatie om informatie bij sessies te registreren.

Het inloggen met 2FA van de administrator hebben we iets anders opgelost, omdat we inloggen van deze gebruiker willen garanderen, ook bij verlies of verkeerde werking van de tokengenerator. Wij hebben ervoor gekozen om het wachtwoord van de administrator maar eenmaal te mogen gebruiken. Voor elke inlogpoging dient het via de Mendix portal te worden gewijzigd.

Wachtwoordbeleid
Het ontwikkelen van een specifiek wachtwoordbeleid kan buiten de Mendix app in HTML/Javascript, met behulp van service calls worden ontwikkeld. Hierbij wordt dan niet gebruik gemaakt van de ontwikkelkracht van Mendix en de oplossing wordt vrij complex. Een goede keus is dan om deze functionaliteit in Mendix te ontwikkelen en het inloggen zodanig te overrulen, dat in plaats van de werkelijke gebruiker, een anonieme gebruiker wordt ingelogd om deze functionaliteit te gebruiken. Na succesvolle authenticatie wordt de werkelijke gebruiker door de app ingelogd. Dit is de aanpak in de eerder genoemde 2FA-module uit de appstore. Diverse mogelijkheden voor het effectief beperken van de rechten van gebruikers komt in een volgende blog aan de orde.

Als slotopmerking is het goed gebruik om voor auditingdoeleinden alle inlogpogingen, succesvol en niet succesvol te loggen.

In een volgende blog Security by design: client API laten we met voorbeelden zien wat er met de client API zoal mogelijk is.