Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api.CredentialsContainer.get.publicKey_option.extensions - largeBlob not working on Chrome Android (130) #25002

Open
flAIght-dev opened this issue Nov 8, 2024 · 0 comments
Labels
data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API

Comments

@flAIght-dev
Copy link

flAIght-dev commented Nov 8, 2024

What type of issue is this?

Incorrect support data (example: BrowserX says "86" but support was added in "40")

What information was incorrect, unhelpful, or incomplete?

largeBlob extension is reported as supported on Android Chrome since 113. Testing it on 130 I am not able to use it.

What browsers does this problem apply to, if applicable?

Chromium (Chrome, Edge 79+, Opera, Samsung Internet)

What did you expect to see?

I expected to be able to read and write a blob

Did you test this? If so, how?

The credential is created without errors. On the write call "written" is undefined. No errors in the read call but the blob is (obviously) empty.

Here is the test code:


  let username = "test"
  let name = "test name"

  const firstSalt = new Uint8Array(new Array(32).fill(1)).buffer;

  navigator.credentials.create({
    publicKey: {
      challenge: Uint8Array.from([1, 2, 3, 4]),
        rp: {
            name: "Example RP",
            id: "api.test.org",
        },
      user: {
        id: Uint8Array.from(username.split("").map(c => c.codePointAt(0))),
        name: name,
        displayName: name,
      },
        pubKeyCredParams: [
            { alg: -8, type: "public-key" },   // Ed25519
            { alg: -7, type: "public-key" },   // ES256
            { alg: -257, type: "public-key" }, // RS256                        
        ],
        authenticatorSelection: {
            userVerification: "required",
            residentKey: "required",
            //requireResidentKey: true
        },

      extensions: {
        prf: {
            eval: {
                first: firstSalt,
            },
        },
        largeBlob: {
          support: "required",
        },
        "credProps": true
      }
    }
  }).then(credential => {
    console.log(credential);
    console.log(credential.getClientExtensionResults());
    window.localStorage.credentialId = arrayBufferToBase64(credential.rawId);

    console.log("Credential successfully created! Try logging in.");

    console.log("extension results " + JSON.stringify(credential.getClientExtensionResults()));

  }).catch(error => {
    console.log(error.toString());
  });

Read blob

navigator.credentials.get({

   publicKey: {
       challenge: new Uint8Array([1, 2, 3, 4]), // Example value
       rp: {
           name: "Example RP",
           id: "api.test.org",
       },
       user: {
           id: Uint8Array.from(username, c => c.charCodeAt(0)), // User-provided ID
           name: username,
           displayName: name,
       },
       pubKeyCredParams: [
           { alg: -8, type: "public-key" },   // Ed25519
           { alg: -7, type: "public-key" },   // ES256
           { alg: -257, type: "public-key" }, // RS256                        
       ],
       authenticatorSelection: {
           userVerification: "required",
           residentKey: "required"
       },
     extensions: {
       largeBlob: {
         read: true
       }
     }
   }

 }).then(assertion => {
   console.log("Blob read", assertion);
   console.log(assertion.getClientExtensionResults());

   console.log("assertion " + assertion);
   console.log("extension results " + JSON.stringify(assertion.getClientExtensionResults()));

   if (assertion.getClientExtensionResults().largeBlob) {
     console.log("Blob found");
     let blobContent = assertion.getClientExtensionResults().largeBlob;
     console.log("blobContent " + blobContent);
     console.log("blobContent type " + (typeof blobContent));
     console.log("blobContent type 2 " + Object.prototype.toString.call(blobContent));
     console.log("blobContent stringify " + JSON.stringify(blobContent));
     let blobString = new TextDecoder().decode(blobContent.blob);
     console.log("blobString: " + blobString);
     console.log("Blob: ", blobString);
     console.log("Blob read successfully! Content: " + blobString);
   } else {
     console.log("No blob found.");
   }
 }).catch(error => {
   console.log(error.toString());
 });

Write blob


  let blobValue = "test blob value"
  
  const blob = new TextEncoder().encode(blobValue);

  console.log("Blob write content: " + blobValue);
  console.log("Blob write content length: " + blob.length);
  console.log("Blob write content encoded: " + Object.prototype.toString.call(blob));

  navigator.credentials.get({
    publicKey: {
        challenge: new Uint8Array([1, 2, 3, 4]), // Example value
        rp: {
            name: "Example RP",
            id: "api.test.org",
        },
        user: {
            id: Uint8Array.from(username, c => c.charCodeAt(0)), // User-provided ID
            name: username,
            displayName: name,
        },
        pubKeyCredParams: [
            { alg: -8, type: "public-key" },   // Ed25519
            { alg: -7, type: "public-key" },   // ES256
            { alg: -257, type: "public-key" }, // RS256                        
        ],
        authenticatorSelection: {
            userVerification: "required",
            residentKey: "required"
        },
      extensions: {
        largeBlob: {
          write: blob
        }
      }
    }
  }).then(assertion => {
    console.log("Blob write attempt", assertion);
    console.log(assertion.getClientExtensionResults());

    if (assertion.getClientExtensionResults().largeBlob.written) {
      console.log("Blob written");
      console.log("Blob written successfully!");

      console.log("write blob stringify " + JSON.stringify(assertion.getClientExtensionResults()));

    } else {
      console.log("Blob not written");
      console.log("Failed to write blob.");
    }
  }).catch(error => {
    console.log(error.toString());
  });

Can you link to any release notes, bugs, pull requests, or MDN pages related to this?

No response

Do you have anything more you want to share?

The same code works fine with Chrome on iOS.

MDN URL

https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API/WebAuthn_extensions

MDN metadata

MDN page report details
  • Query: api.CredentialsContainer.get.publicKey_option.extensions
  • Report started: 2024-11-08T12:29:50.653Z
@queengooborg queengooborg added the data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API label Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
data:api 🐇 Compat data for Web APIs. https://developer.mozilla.org/docs/Web/API
Projects
None yet
Development

No branches or pull requests

2 participants