Diese Web -App ist eine Demo für meine WebAuthn -Serverbibliothek (FXAMACKER/WebAuthn). Es unterstützt die Registrierung und Authentifizierung von WebAuthn. Es implementiert die vorgeschlagene REST -API für FIDO2 -Server.

WebAuthn (Web Authentifizierung) ist ein W3C-Webstandard für die Authentifizierung von Benutzern mit webbasierten Apps und Diensten. Es ist eine Kernkomponente von FIDO2, dem Nachfolger von FIDO U2F -Legacy -Protokoll.
Diese Demo ist nicht für die Produktionsnutzung gedacht, da sie als Demo ausgelegt ist.
go get github.com/fxamacker/webauthn-demo
$ CERTS_DIR=[folder containing cert.pem and key.pem] docker-compose up
Die WebAuthn -Demo läuft unter https: // localhost: 8443 auf Ihrem Docker -Host.
$ docker-compose up
Die WebAuthn -Demo läuft unter https: // localhost: 8443 auf Ihrem Docker -Host.
Der Registrierungsprozess besteht aus zwei Schritten: Erstellen Sie Optionen zur Erstellung von Anmeldeinformationen und registrieren Sie Anmeldeinformationen. Siehe Signup.html, WebAuthn.register.js und Registration_handlers.go.
Erstellen Sie Optionen zur Erstellung von Anmeldeinformationen:
Die Anfrage des Servers /attestation/options durch Rückgabe von Optionen für die Erstellung von Anmeldeinformationen (PublicKeycredentialcreationoptions) an den Kunden. Client verwendet dann diese Optionen mit navigator.credentials.create() um neue Anmeldeinformationen zu erstellen.
// Simplified `/attestation/options` handler from registration_handlers.go
func (s *server) handleAttestationOptions(w http.ResponseWriter, r *http.Request) {
// Get user from datastore by username.
u, _ := s.dataStore.getUser(r.Context(), optionsRequest.Username)
// Create PublicKeyCredentialCreationOptions using webauthn library.
creationOptions, _ := webauthn.NewAttestationOptions(s.webAuthnConfig, &webauthn.User{ID: u.UserID, Name: u.UserName, DisplayName: u.DisplayName, CredentialIDs: u.CredentialIDs})
// Save creationOptions and user info in session to verify new credential later.
session.Values[WebAuthnCreationOptions] = creationOptions
session.Values[UserSession] = &userSession{User: u}
// Write creationOptions to response.
}
Registrieren Sie Anmeldeinformationen:
Der Server überprüft und registriert neue Anmeldeinformationen, die über /attestation/result empfangen werden.
// Simplified `/attestation/result` handler from registration_handlers.go
func (s *server) handleAttestationResult(w http.ResponseWriter, r *http.Request) {
// Get saved creationOptions and user info from session.
// Parse and verify credential in request body.
credentialAttestation, _ := webauthn.ParseAttestation(r.Body)
expected := &webauthn.AttestationExpectedData{
Origin: s.rpOrigin,
RPID: savedCreationOptions.RP.ID,
CredentialAlgs: credentialAlgs,
Challenge: base64.RawURLEncoding.EncodeToString(savedCreationOptions.Challenge),
UserVerification: savedCreationOptions.AuthenticatorSelection.UserVerification,
}
_, _, err = webauthn.VerifyAttestation(credentialAttestation, expected)
// Save user credential in datastore.
c := &credential{
CredentialID: credentialAttestation.RawID,
UserID: uSession.User.UserID,
Counter: credentialAttestation.AuthnData.Counter,
CoseKey: credentialAttestation.AuthnData.Credential.Raw,
}
err = s.dataStore.addUserCredential(r.Context(), uSession.User, c)
// Write "ok" response.
}
Der Authentifizierungsprozess erfordert zwei Schritte: Erstellen Sie Optionen für Anmeldeinformationen und überprüfen Sie die Anmeldeinformationen. Siehe signin.html, webauthn.authn.js und authentication_handllers.go.
Erstellen Sie Optionen für Anmeldeinformationen: Optionen:
Die Anfrage des Server Handles /assertion/options , indem Anmeldeinformationsanforderungen Optionen (PublicKeycredentialRequestOptions) an den Client zurückgeben. Der Client verwendet dann diese Optionen mit navigator.credentials.get() um vorhandene Anmeldeinformationen zu erhalten.
// Simplified `/assertion/options` handler from authentication_handlers.go
func (s *server) handleAssertionOptions(w http.ResponseWriter, r *http.Request) {
// Get user from datastore by username.
u, _ := s.dataStore.getUser(r.Context(), optionsRequest.Username)
// Create PublicKeyCredentialRequestOptions using webauthn library.
requestOptions, _ := webauthn.NewAssertionOptions(s.webAuthnConfig, &webauthn.User{ID: u.UserID, Name: u.UserName, DisplayName: u.DisplayName, CredentialIDs: u.CredentialIDs})
// Save requestOptions and user info in session to verify credential later.
session.Values[WebAuthnRequestOptions] = requestOptions
session.Values[UserSession] = &userSession{User: u}
// Write requestOptions to response.
}
Überprüfen Sie die Anmeldeinformationen:
Server überprüft Anmeldeinformationen, die über /asssertion/result empfangen werden.
// Simplified `/assertion/result` handler from authentication_handlers.go
func (s *server) handleAssertionResult(w http.ResponseWriter, r *http.Request) {
// Get saved requestOptions and user info.
// Parse credential in request body.
credentialAssertion, _ := webauthn.ParseAssertion(r.Body)
// Get credential from datastore by received credential ID.
c, _ := s.dataStore.getCredential(r.Context(), uSession.User.UserID, credentialAssertion.RawID)
// Verify credential.
expected := &webauthn.AssertionExpectedData{
Origin: s.rpOrigin,
RPID: savedRequestOptions.RPID,
Challenge: base64.RawURLEncoding.EncodeToString(savedRequestOptions.Challenge),
UserVerification: savedRequestOptions.UserVerification,
UserID: uSession.User.UserID,
UserCredentialIDs: userCredentialIDs,
PrevCounter: c.Counter,
Credential: credKey,
}
err = webauthn.VerifyAssertion(credentialAssertion, expected)
// Update authenticator counter in datastore.
c.Counter = credentialAssertion.AuthnData.Counter
err = s.dataStore.updateCredential(r.Context(), c)
// Write "ok" response.
}
Für die neueste veröffentlichte Version werden Sicherheitsfixes bereitgestellt.
Um Sicherheitslücken zu melden, senden Sie bitte eine E -Mail an [email protected] und nehmen Sie Zeit, damit das Problem behoben werden kann, bevor Sie es der Öffentlichkeit melden.
Copyright (C) 2019-Präsentation Faye Amacker
FXAMACKER/WebAuthn-Demo ist unter der Apache-Lizenz, Version 2.0, lizenziert. Siehe Lizenz für den vollständigen Lizenztext.