spinny:~/writing $ less passkeys-webauthn-passwordless-authentication.md
12Οι κωδικοί πρόσβασης είναι ένα από εκείνα τα πράγματα που έχουμε κανονικοποιήσει μόνο και μόνο επειδή ζούμε με αυτούς για χρόνια. Οι χρήστες τα ξεχνούν, τα επαναχρησιμοποιούν, τα γράφουν εκεί που δεν πρέπει. Οι ομάδες πρέπει να διαχειρίζονται επαναφορές, πολιτικές, κατακερματισμούς, διαρροές, ηλεκτρονικό ψάρεμα και υποστήριξη.34Τα passkey δεν κάνουν τον έλεγχο ταυτότητας τέλειο, αλλά αφαιρούν ένα τεράστιο πρόβλημα: ο διακομιστής δεν χρειάζεται πλέον να κρατά ένα μυστικό κοινόχρηστο με τον χρήστη.56## Τι πραγματικά συμβαίνει78Το passkey είναι ένα διαπιστευτήριο που βασίζεται στο WebAuthn. Όταν ο χρήστης το δημιουργεί, η συσκευή δημιουργεί ένα ζεύγος κλειδιών:910- ένα ιδιωτικό κλειδί, το οποίο παραμένει στη συσκευή ή στη διαχείριση κωδικών πρόσβασης.11- ένα δημόσιο κλειδί, το οποίο μπορεί να αποθηκεύσει ο διακομιστής.1213Όταν συνδέεστε στον διακομιστή δεν ρωτά "πες μου τον κωδικό πρόσβασης". Στείλτε μια τυχαία πρόκληση. Η συσκευή το υπογράφει με το ιδιωτικό κλειδί. Ο διακομιστής επαληθεύει την υπογραφή με το δημόσιο κλειδί.1415Αυτό είναι το ωραίο μέρος: εάν κλαπεί η βάση δεδομένων, δεν υπάρχουν κωδικοί πρόσβασης μέσα για να σπάσουν. Και αν ένας χρήστης καταλήξει σε έναν ψεύτικο τομέα, το passkey δεν ισχύει για αυτόν τον τομέα. Δεν είναι απλώς ευκολία, είναι συγκεκριμένη προστασία από το phishing.1617## Το πρόγραμμα περιήγησης λειτουργεί ως γέφυρα1819Στο πρόγραμμα περιήγησης τα δύο κύρια API είναι:2021- `navigator.credentials.create()` για να δημιουργήσετε ένα passkey.22- `navigator.credentials.get()` για να το χρησιμοποιήσετε κατά τη σύνδεση.2324Αλλά η σημαντική λογική βρίσκεται στον διακομιστή. Ο διακομιστής πρέπει να δημιουργήσει την πρόκληση, να την αποθηκεύσει προσωρινά, να επαληθεύσει την απόκριση, να ελέγξει την πηγή και Relying Party ID και, στη συνέχεια, να δημιουργήσει τη συνεδρία.2526Το τμήμα πελάτη πρέπει να είναι σχεδόν βαρετό:2728```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());3031const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});3435await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```4142Εάν διαπιστώσετε ότι εφαρμόζετε την κρυπτογράφηση WebAuthn με το χέρι, σταματήστε. Χρησιμοποιήστε μια ισχυρή βιβλιοθήκη από την πλευρά του διακομιστή. Τα σφάλματα εδώ δεν είναι "χαριτωμένα σφάλματα", είναι τρύπες ελέγχου ταυτότητας.4344## Τι να αποθηκεύσετε στη βάση δεδομένων4546Δεν υπάρχει λόγος να σώσουμε τον μισό κόσμο. Συνήθως αρκετά:4748- Ταυτότητα του διαπιστευτηρίου49- δημόσιο κλειδί50- συνδεδεμένος χρήστης.51- τυχόν μετρητή επαλήθευσης ή μεταδεδομένα·52- μεταφορές, εάν είναι χρήσιμες για το UX.53- όνομα που επιλέγει ο χρήστης.54- ημερομηνία δημιουργίας και τελευταία χρήση.5556Ένας ελάχιστος πίνακας μπορεί να μοιάζει με αυτό:5758```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```6970Στη συνέχεια, θα πρόσθετα αρχεία καταγραφής ελέγχου και ειδοποιήσεις: εάν κάποιος δημιουργήσει ένα νέο passkey στον λογαριασμό μου, θέλω να το μάθω.7172## Το UX έχει μεγαλύτερη σημασία από την επίδειξη7374Το demo ενός passkey είναι πάντα όμορφο: κάνετε κλικ, Face ID, είστε μέσα. Το πραγματικό προϊόν είναι πιο περίπλοκο.7576Κάποιος αλλάζει το τηλέφωνό του. Κάποιος χρησιμοποιεί έναν κλειδωμένο υπολογιστή της εταιρείας. Μερικοί άνθρωποι δεν καταλαβαίνουν γιατί το πρόγραμμα περιήγησης προτείνει ένα passkey. Κάποιος χάνει την πρόσβαση στη συσκευή του.7778Αυτός είναι ο λόγος που δεν θα ξεκινούσα με το "από σήμερα δεν υπάρχουν άλλοι κωδικοί πρόσβασης για όλους". Θα ξεκινούσα ως εξής:79801. passkey προαιρετικό για εσωτερικούς χρήστες.812. Πρόταση για δημιουργία μετά από επιτυχή σύνδεση.823. σελίδα λογαριασμού για μετονομασία και κατάργηση passkey.834. σαφές εναλλακτικό.845. σταδιακή διάθεση στην κύρια είσοδο.8586Το κείμενο στη διεπαφή πρέπει να είναι απλό. Η "Χρήση της οθόνης κλειδώματος της συσκευής σας" είναι καλύτερη από την "επαλήθευση ταυτότητας με διαπιστευτήριο κατοίκου FIDO2".8788## Λάθη που θα απέφευγα8990Μην δημιουργείτε προκλήσεις στον πελάτη. Η πρόκληση δημιουργείται στον διακομιστή και πρέπει να επαληθευτεί μόνο μία φορά.9192Μην εμπιστεύεστε μόνο το αναγνωριστικό διαπιστευτηρίων. Πρέπει να επαληθεύσετε την υπογραφή, την πρόκληση, την προέλευση και το Relying Party ID.9394Μην διαγράφετε εναλλακτικές προτού να έχετε μια καλή ροή ανάκτησης. Χωρίς κωδικό πρόσβασης δεν χρειάζεται να γίνει "αν χάσετε το τηλέφωνό σας, θα είστε για πάντα έξω".9596Μην αντιμετωπίζετε το passkey ως ένα κουμπί καθαρά frontend. Η απόκρυψη ενός κουμπιού δεν είναι ασφάλεια: η πραγματική επαλήθευση είναι από την πλευρά του διακομιστή.9798## Passkey-πρώτος ή passkey-φιλικός;99100Για ένα νέο προϊόν μπορείτε να σκεφτείτε πρώτα passkey. Για μια υπάρχουσα εφαρμογή προτιμώ φιλική προς το passkey: προσθέστε το passkey ως προτεινόμενη μέθοδο, μετρήστε την επιτυχία και τα προβλήματα και, στη συνέχεια, μειώστε ήρεμα το βάρος του κωδικού πρόσβασης.101102Η ιδανική μετανάστευση δεν γίνεται αισθητή. Ο χρήστης ανακαλύπτει ότι η σύνδεση είναι ευκολότερη και όχι ότι η εταιρεία έχει αλλάξει το πρωτόκολλο ελέγχου ταυτότητας.103104## Συμπέρασμα105106Τα passkey είναι ενδιαφέροντα γιατί βελτιώνουν την ασφάλεια και το UX ταυτόχρονα, κάτι που είναι σπάνιο. Δεν είναι ένα μαγικό ραβδί: η ανάκτηση, η συμβατότητα, η υποστήριξη και η διάθεση πρέπει να σχεδιαστούν σωστά.107108Αλλά η βασική αλλαγή είναι ισχυρή. Σταματήστε να ζητάτε από τους χρήστες να εφεύρουν και να προστατεύουν μυστικά. Αφήνετε τη συσκευή να υπογράψει μια κρυπτογραφική απόδειξη που συνδέεται με τον τομέα σας. Λιγότερη ανθρώπινη μνήμη, λιγότερο phishing, λιγότερες επαναφορές κωδικών πρόσβασης. Θα έλεγα ότι αξίζει να ληφθούν σοβαρά υπόψη.109110## Πηγές111112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116
:Passkey και WebAuthn: συνδεθείτε χωρίς κωδικό πρόσβασης, χωρίς μαγείαlines 1-116 (END) — press q to close