WebAuthn: ejemplo de uso avanzado

· Componentes

A continuación se muestra un ejemplo más completo en Delphi que demuestra endpoints personalizados, políticas de challenge, almacenamiento de credenciales en base de datos, validación con FIDO Metadata y soporte de iframes cross-origin. El código resalta el manejo avanzado de eventos para aplicar políticas de seguridad. 

Ejemplo de servidor WebAuthn con sgcWebSockets

procedure TForm1.ConfigureWebAuthn;
begin
  // Component setup
  FWebAuthn := TsgcWSAPIServer_WebAuthn.Create(nil);
  FWebAuthn.Server := FHTTPServer;
  FWebAuthn.Enabled := True;
  // Endpoint remapping
  FWebAuthn.EndpointOptions.AuthenticationOptions := '/auth/options';
  FWebAuthn.EndpointOptions.AuthenticationVerify  := '/auth/verify';
  FWebAuthn.EndpointOptions.RegistrationOptions   := '/reg/options';
  FWebAuthn.EndpointOptions.RegistrationVerify    := '/reg/verify';
  // Relying-party definition
  with FWebAuthn.WebAuthnOptions do
  begin
    RelyingParty := 'secure.example.com';
    Origins      := 'https://app.example.com;https://login.example.net';
    TopOrigins   := 'https://host.example.org';
    AllowCrossOrigins := True;
    // Cryptographic & UX policies
    Algorithms       := 'ES256,RS256';
    UserVerification := 'preferred';
    Attestation      := 'direct';
    TimeoutMS        := 60000;
    // Challenge settings
    ChallengeOptions.ChallengeSize := 64; // 512-bit challenges
    ChallengeOptions.RandomFunc    := MyCryptoRandom; // custom RNG
    // Metadata Service configuration
    MDS.Enabled            := True;
    MDS.MDS_FileName       := 'mds.json';
    MDS.RootCert_FileName  := 'root.pem';
  end;
  // Hook events
  FWebAuthn.OnWebAuthnRegistrationOptionsRequest := AuthnRegOptionsRequest;
  FWebAuthn.OnWebAuthnRegistrationVerify         := AuthnRegVerify;
  FWebAuthn.OnWebAuthnRegistrationSuccessful     := AuthnRegSuccess;
  FWebAuthn.OnWebAuthnAuthenticationOptionsRequest := AuthnOptionsRequest;
  FWebAuthn.OnWebAuthnAuthenticationVerify         := AuthnVerify;
  FWebAuthn.OnWebAuthnAuthenticationSuccessful     := AuthnSuccess;
end;

Implementaciones de eventos

procedure TForm1.AuthnRegOptionsRequest(Sender: TObject;
  const Request: TsgcWebAuthnRequestOptions; Response: TsgcWebAuthnResponseOptions);
begin
  // Verify user is eligible for registration
  if UserExists(Request.Username) then
    raise Exception.Create('Username already registered');
  // Optionally assign a user handle (binary identifier)
  Response.User.ID := HexToBin(UserGUIDToHex(GenerateGUID));
  Response.AuthenticatorSelection.AuthenticatorAttachment := 'platform';
end;
procedure TForm1.AuthnRegVerify(Sender: TObject; const Credential: TsgcWebAuthnCredential; var Success: Boolean);
begin
  // Perform extra attestation validation against MDS entries
  Success := ValidateAttestationWithMDS(Credential);
end;
procedure TForm1.AuthnRegSuccess(Sender: TObject; const Credential: TsgcWebAuthnCredential);
begin
  // Persist credential details in database
  SaveCredentialToDB(
    Credential.Username,
    Credential.CredentialID,
    Credential.PublicKey,
    Credential.SignCount,
    Credential.UserHandle
  );
end;
procedure TForm1.AuthnOptionsRequest(Sender: TObject;
  const Request: TsgcWebAuthnRequestOptions; Response: TsgcWebAuthnResponseOptions);
begin
  // Retrieve all credential IDs for user
  Response.AllowCredentials := LoadCredentialIdsFromDB(Request.Username);
end;
procedure TForm1.AuthnVerify(Sender: TObject; const Credential: TsgcWebAuthnCredential; var Success: Boolean);
var
  StoredCounter: Cardinal;
begin
  // Ensure sign counter increases
  StoredCounter := GetSignCounterFromDB(Credential.CredentialID);
  if Credential.SignCount <= StoredCounter then
    Success := False
  else
    Success := True;
end;
procedure TForm1.AuthnSuccess(Sender: TObject; const Credential: TsgcWebAuthnCredential);
begin
  UpdateSignCounterInDB(Credential.CredentialID, Credential.SignCount);
  IssueSessionToken(Credential.Username);
end;

Puntos destacados

  1. Endurecimiento del challenge – Al ampliar el tamaño del challenge y usar un RNG criptográficamente seguro, se mitigan aún más los ataques de replay.
  2. User handles personalizados – Asignar un user handle binario único permite que el autenticador almacene un identificador respetuoso con la privacidad, independiente de los nombres de usuario.
  3. Validación de atestación basada en metadatos – La rutina ValidateAttestationWithMDS verifica el modelo del autenticador, los informes de estado y las listas de revocación, garantizando que solo se registren dispositivos de confianza.
  4. Aplicación estricta del contador de firmasAuthnVerify rechaza respuestas que no incrementen estrictamente el contador del autenticador, detectando credenciales clonadas.
  5. Integración con base de datos – Los datos de credenciales, los contadores de firmas y los tokens de sesión se almacenan y actualizan mediante funciones externas de persistencia, mostrando cómo integrar el componente con un backend real.
  6. Soporte de iframe cross-origin – Se activa con AllowCrossOrigins y configurando TopOrigins, lo que permite flujos WebAuthn iniciados desde frames incrustados (p. ej., un widget de inicio de sesión en un dominio distinto).
  7. Política de atestación – La atestación directa junto con MDS asegura que solo se puedan registrar autenticadores aprobados, útil para escenarios de cumplimiento empresarial.
  8. Selección de transporte – Aunque no se muestra, los eventos pueden restringir los transportes aceptables (p. ej., USB,NFC,BLE) para acotar qué tipos de autenticadores se permiten.