该网络应用程序是我的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的许可。有关完整许可文本,请参见许可证。