該網絡應用程序是我的WebAuthn服務器庫(FXAMACKER/WEBAUTHN)的演示。它支持WebAuthn註冊和身份驗證。它為FIDO2服務器提供了建議的REST API。

WebAuthn(Web身份驗證)是W3C Web標準,用於為用戶身份驗證基於Web的應用程序和服務。它是Fido U2F Legacy協議的繼任者Fido2的核心組成部分。
該演示不供生產使用,因為它設計為演示。
go get github.com/fxamacker/webauthn-demo
$ CERTS_DIR=[folder containing cert.pem and key.pem] docker-compose up
Webauthn演示在https:// localhost:8443在您的Docker主機上運行。
$ docker-compose up
Webauthn演示在https:// localhost:8443在您的Docker主機上運行。
註冊過程包括兩個步驟:創建憑據創建選項和註冊憑據。請參閱Ingip.html,webauthn.register.js和registration_handlers.go。
創建憑證創建選項:
通過將憑據創建選項(PublicKeyCredentialCreationOptions)返回客戶端,服務器處理/attestation/options請求。然後,客戶端將這些選項與navigator.credentials.create()一起創建新憑據。
// 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.
}
註冊憑據:
服務器驗證並註冊通過/attestation/result收到的新憑據。
// 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.
}
身份驗證過程需要兩個步驟:創建憑據請求選項並驗證憑據。請參閱signin.html,webauthn.authn.js和authentication_handlers.go。
創建憑據請求選項:
通過將憑據請求選項(publicKeycredentialRequestoptions)返回客戶端,服務器處理/assertion/options請求。然後,客戶端將這些選項與navigator.credentials.get()一起獲取現有憑據。
// 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.
}
驗證憑據:
服務器驗證通過/asssertion/result收到的憑據。
// 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.
}
為最新發布的版本提供了安全修復程序。
要報告安全漏洞,請發送電子郵件至[email protected],並在向公眾報告之前,請花時間解決問題。
版權(c)2019-Present Faye Amacker
FXAMACKER/WEBAUTHN-DEMO已獲得Apache許可證版本2.0的許可。有關完整許可文本,請參見許可證。