Este aplicativo da Web é uma demonstração para minha biblioteca de servidores webauthn (FXAMACKER/WEBAUTHN). Ele suporta registro e autenticação da WebAuthn. Ele implementa a API REST proposta para servidores fido2.

O WebAuthn (Web Authentication) é um padrão da Web W3C para autenticar usuários para aplicativos e serviços baseados na Web. É um componente central do Fido2, o sucessor do protocolo Fido U2F Legacy.
Esta demonstração não é para uso da produção porque foi projetado para ser uma demonstração.
go get github.com/fxamacker/webauthn-demo
$ CERTS_DIR=[folder containing cert.pem and key.pem] docker-compose up
A demonstração do WebAuthn é executada em https: // localhost: 8443 no seu host do Docker.
$ docker-compose up
A demonstração do WebAuthn é executada em https: // localhost: 8443 no seu host do Docker.
O processo de registro consiste em duas etapas: Crie opções de criação de credenciais e registre credenciais. Consulte SignUp.html, webauthn.register.js e registration_handlers.go.
Crie opções de criação de credenciais:
Solicitação de manipulação do servidor /attestation/options retornando opções de criação de credenciais (publicKeyCredentialCeationOptions) ao cliente. O cliente usa essas opções com navigator.credentials.create() para criar novas credenciais.
// 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.
}
Registre credenciais:
O servidor verifica e registra novas credenciais recebidas via /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.
}
O processo de autenticação requer duas etapas: crie opções de solicitação de credencial e verifique as credenciais. Consulte Signin.html, webauthn.authn.js e autentication_handlers.go.
Crie opções de solicitação de credencial:
Solicitação de manipulação /assertion/options do servidor, retornando opções de solicitação de credencial (publicKeyCredentialRequestOptions) ao cliente. O cliente usa essas opções com navigator.credentials.get() para obter credenciais existentes.
// 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.
}
Verifique as credenciais:
O servidor verifica as credenciais recebidas via /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.
}
As correções de segurança são fornecidas para a versão mais recente lançada.
Para relatar vulnerabilidades de segurança, envie um email para [email protected] e permita que o problema seja resolvido antes de relatá -lo ao público.
Copyright (c) 2019-presente Faye Amacker
O fxamacker/webauthn-Demo é licenciado sob a licença Apache, versão 2.0. Consulte a licença para o texto completo da licença.