Implementing WebAuthn via LiveView

Update

I’ve made significant progress on this over the past weeks. In Chrome (and Safari - see next reply), I can register and login using TouchID or a USB key via WebAuthn. :tada: To share what I’ve been learning, I started live streaming via Twitch.

Today, I encountered an error when I attempted to register in Safari. The attestation statement is coming back with an invalid format. pubKeyCredParams is configured as recommended by webauthn.guide and MDN docs, so I don’t understand why Safari/WebKit is returning a different format. Has anyone else seen this?

Safari: Invalid attStmt

attestation_decoded: {:ok,
 %{
   "attStmt" => %{
     "x5c" => [
       %CBOR.Tag{
         tag: :bytes,
         value: <<48, 130, 2, 66, 48, 130, 1, 201, 160, 3, 2, 1, 2, 2, 6, 1,
           128, 124, 231, 151, 17, 48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, 2,
           48, 72, 49, 28, 48, 26, 6, 3, 85, 4, ...>>
       },
       %CBOR.Tag{
         tag: :bytes,
         value: <<48, 130, 2, 52, 48, 130, 1, 186, 160, 3, 2, 1, 2, 2, 16, 86,
           37, 83, 149, 199, 167, 251, 64, 235, 226, 40, 216, 38, 8, 83, 182,
           48, 10, 6, 8, 42, 134, 72, 206, 61, 4, 3, ...>>
       }
     ]
   },
   "authData" => %CBOR.Tag{
     tag: :bytes,
     value: <<73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100, 118,
       96, 91, 143, 228, 174, 185, 162, 134, 50, 199, 153, 92, 243, 186, 131,
       29, 151, 99, 69, 0, 0, 0, 0, 242, 74, 142, 112, 208, 211, 248, ...>>
   },
   "fmt" => "apple"
 }, ""}

Chrome: Valid attStmt

attestation_decoded: {:ok,
%{
  "attStmt" => %{
    "alg" => -7,
    "sig" => %CBOR.Tag{
      tag: :bytes,
      value: <<48, 69, 2, 32, 47, 29, 113, 135, 145, 72, 34, 17, 253, 171, 217,
        197, 203, 183, 23, 136, 9, 11, 218, 71, 128, 245, 55, 104, 177, 220,
        10, 73, 42, 207, 157, 7, 2, 33, 0, 158, 243, 192, 200, ...>>
    }
  },
  "authData" => %CBOR.Tag{
    tag: :bytes,
    value: <<73, 150, 13, 229, 136, 14, 140, 104, 116, 52, 23, 15, 100, 118,
      96, 91, 143, 228, 174, 185, 162, 134, 50, 199, 153, 92, 243, 186, 131,
      29, 151, 99, 69, 98, 109, 204, 235, 173, 206, 0, 2, 53, 188, 198, ...>>
  },
  "fmt" => "packed"
}, ""}

Public Key Config

const publicKey = {
  challenge: challenge.buffer,
  rp: {
    name: appName,
    id: rp_id,
  },
  user: {
    id: new Uint8Array(16).buffer,
    name: user.email,
    displayName: user.username,
  },
  pubKeyCredParams: [{ alg: -7, type: "public-key" }],
  timeout: 60000,
  attestation: attestation,
  authenticatorSelection: {
    userVerification: user_verification,
  },
};