2FA toevoegen aan project
Is het veilig de code zomaar bij het user account te bewaren in de database of hoe pak ik dat aan?
Al denk ik dat je jezelf heel goed moet afvragen of gebruik van Google diensten wel AVG-technisch wel door de beugel kan, over het algemeen is Google wat dat betreft puur gif. (Alleen al het aanbieden van lettertypen bij Google vandaan heeft een Duits bedrijf een boete opgeleverd).
Wat betreft de term sleutel, die vond ik in het begin lastig te begrijpen, omdat zowel de publieke sleutel als de private sleutel 'sleutel' worden genoemd. De werking bleek simpel, de publieke sleutel is publiek, en wordt gebruikt om mee te versleutelen. Maar alleen degene met de private sleutel kan de gegevens ontsleutelen.
Voor de rest is de werking dus hetzelfde als met het wachtwoord. Je slaat het wachtwoord niet op in de database, je slaat alleen de hash op. Als iemand een wachtwoord instuurt om te authenticeren, check je dat wachtwoord met de hash.
Nu met sleutels. Je slaat de publieke sleutel op in de database. Als iemand de private sleutel instuurt om te authenticeren, kan je beide sleutels gebruiken om iets te versleutelen en te ontsleutelen en zo valideren of de sleutels bij elkaar horen.
Na elke aanmeldpoging, gelukt of niet, wis je het wachtwoord en de private sleutel weer.
Net als met het genereren van wachtwoorden kan je ook een sleutelpaar laten genereren op het authenticatiesysteem, en dan bied je daarna de private sleutel aan als download. Je bewaart dan alleen de publieke sleutel.
Het is aan de gebruiker om zijn wachtwoorden / cryptografische sleutels te bewaren. Als je dat meteen goed wilt doen loont het om op zoek te gaan naar een goede wachtwoordmanager. Mocht je geen goede keuze kunnen maken dan is KeePass een goede optie. Met een add-on is de interface in het Nederlands te krijgen.
OTP is toch niet iets van Google trouwens?
Een OTP op zichzelf is geen 2FA, maar een extra wachtwoord (dat maar van korte duur geldig is). Het idee is dat je dat wachtwoord gebruikt om iets anders te valideren, bijvoorbeeld iemands mobiele telefoonnummer, of een e-mailadres.
2FA (of gewoon multifactorauthenticatie) is dat een gebruiker zich authenticeert op 2 of meer manieren, waarbij onder manieren wordt verstaan:
1. iets wat iemand weet
2. iets wat iemand heeft
3. iets wat iemand is
Met andere woorden, als je gaat scannen met een QR code, moet je wel voor jezelf scherp hebben dat je niet een tweede keer authenticeert op basis van punt 1., want tweemaal een wachtwoord is geen 2FA. In het geval met de Google app zou ik niet weten op basis waarvan authenticatie verloopt, want Google mag niet zomaar binnen de EU worden ingezet voor iets dergelijks.
Dit alles gezegd hebbende, een tijdelijk gegenereerde sleutel (OTP) kan je best in een database opslaan. Als het heel tijdelijk is, zeg een paar minuten, is de kans op problemen niet heel groot. Maar dan moet je het wel onzettend veilig opslaan, zodat niemand anders daar bij kan. In complexe omgevingen zoals in de cloud kan het lastig zijn om dat goed te regelen.
Het blijft raadzaam om de OTP te genereren en uit te geven, en van de OTP alleen een hash op te slaan. Je zou hiervoor password_hash() en password_verify() kunnen gebruiken. Juist omdat OTP slechts een (tijdelijk) wachtwoord is, zou het niet moeilijk moeten zijn.
1. iets wat iemand weet > pass
2. iets wat iemand heeft > otp
3. iets wat iemand is > user
Het probleem zit hem in het feit dat ik niet weet hoe de OTP te genereren zonder de secret te kennen. Ik zou dan user, hashpass en secret op moeten slaan, maar is dat veilig?
Gewijzigd op 09/03/2022 15:59:35 door Veur Heur
Zoals ik het dus zie, zal ik de secretkey dus toch gewoon bij het account op moeten slaan.
OTP is wat de naam al aangeeft, een wachtwoord dat eenmalig geldig is (One Time Password). En meestal heeft die ook maar een (zeer) beperkte geldigheidsduur, zoals een SMS-code die maar 2 minuten werkt.
En je ziet het goed, je moet inderdaad de 'secretkey' opslaan. Maar als je dat veilig wilt doen, is de eenvoudigste manier om een OTP-wachtwoord (de secretkey) te genereren, die aan de gebruiker te geven, en zelf alleen de hash op te slaan, net zoals je dat zou moeten doen met alle andere wachtwoorden. Hiervoor heeft PHP password_hash() en password_verify(). Als wachtwoord kan je gewoon een willekeurige reeks karakters genereren met random_bytes().
Je kunt een stap verder gaan met mijn eerste reactie. Het idee is hetzelfde maar in plaats van een OTP-wachtwoord gebruik je een cryptografisch sleutelpaar, waarbij je de public key opslaat en de private key aan de gebruiker geeft.
Als iemand probeert te authenticeren met zijn of haar accountnaam dan krijg je:
1. iets wat iemand weet --> het wachtwoord van de account
2. iets wat iemand heeft --> de private key, of elke keer een device controleren met een OTP
3. iets wat iemand is --> dit is meestal biometrie (vingerafdruk, gezichtsherkenning, DNA etc.)
Punt 3 is niet aan de orde, maar punt 2 is nu wel duidelijk. Het is van belang dat je bij punt 2 valideert wat iemand heeft, in de strikte zin, anders maakt een auditbureau gehakt van je authenticatie (dat is mijn ervaring).
Toevoeging op 10/03/2022 09:41:32:
Adoptive Solution op 09/03/2022 18:41:39:
Die verwijst naar Google Authenticator. Dat moet je niet willen als je iets ontwikkelt voor gebruik binnen de EU.