gavinsawyer / firebase-web-authn

A Firebase Extension for authentication with WebAuthn passkeys. Hire the developer: /in/gavinsawyer-dev.
https://extensions.dev/extensions/gavinsawyer/firebase-web-authn
Apache License 2.0
39 stars 2 forks source link

Firebase function returning Unauthenticated #8

Closed titocosta closed 1 year ago

titocosta commented 1 year ago

Trying out firebase-web-authn on a NextJS 13 application hosted on localhost.

I am getting the following error when the /firebase-web-authn-api firebase function gets invoked by signInWithPasskey:

{error: {message: "Unauthenticated", status: "UNAUTHENTICATED"}}

I am using NextJS 13 with a rewrite to reverse proxy the call to the function as below.

const nextConfig = {
  async rewrites() {
    return [
      {
        source: "/firebase-web-authn-api",
        destination: "https://us-central1-project-id.cloudfunctions.net/ext-firebase-web-authn-api"
      },
    ];
  }
}

module.exports = nextConfig

I added allUsers principals to the Cloud Function Invoker role to allow the function to be called openly.

Any suggestions? Does the app need to be hosted on firebase hosting in order for the extension to work?

gavinsawyer commented 1 year ago

Hi Tito,

Sorry you're having trouble. This may have been due to a Firebase Auth error on signInWithCustomToken which was caught incorrectly and fixed in v10.1.5. If there was an issue there, you should be receiving a different error message after updating.

Right now, the demo site is broken with either the same issue as you or with the error "auth/network-request-failed." This appears to be because of discrepancies in private class members in AngularFire v16's Auth object and that of Firebase JS SDK v10. I'm noticing more areas of FirebaseWebAuthn that aren't stable, but it's difficult to test without rebuilding an app that uses the Firebase JS SDK directly. I haven't been able to officially publish new extension versions anyways since Firebase Tools can't seem to recognize versions >10... Overall there are ecosystem issues getting in the way of v10 which I'm still thinking through.

I'd recommend trying for a new error message on v10.1.5 or downgrading to v9 if possible.

I also suspect this could be an issue with Firebase Hosting. Just to be sure, that's not the actual destination URL you're using, correct? It should contain your actual project ID. It's also calling the deployed function and not an emulator, right?

Here's how my function's access config looks in Google Cloud Console, also:

Function access config in Google Cloud Console

Let me know if anything here works or if I can take a look at your source code.

gavinsawyer commented 1 year ago

Just fixed the demo by not importing firebase so I'm not sure if any of my issues were the same actually... Anyways try v10.1.5 and let me know what changed if anything.

titocosta commented 1 year ago

Hi Gavin, thanks for taking a look. project-id / emulator shouldn't be my issue.

I am still learning about firebase extensions. I am on version 9.6.6 which seems to be the latest available at https://extensions.dev/extensions/gavinsawyer/firebase-web-authn

I don't see an update button on my console page https://console.firebase.google.com/u/0/project/supertext-d3f2b/extensions/instances/firebase-web-authn?tab=config

Can I update via npm to 10.1.5?

titocosta commented 1 year ago

I previously had @firebase-web-authn/browser 10.1.0 and I now upgraded to 10.2.1 with npm i @firebase-web-authn/browser@latest. [On Firebase console I am still on 9.6.6, maybe it refers to the cloud function].

Basically still same {message: "Unauthenticated", status: "UNAUTHENTICATED"} error message.

This is the call that happens in the backend (from chrome dev tools, copy as cURL). It gets called with an authorization bearer header from an anonymous firebase user. If i remove that, same outcome.

curl 'http://localhost:3000/firebase-web-authn-api' \
  -H 'Accept: */*' \
  -H 'Accept-Language: en-US,en;q=0.9,it;q=0.8' \
  -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MGFkMTE4YTk0MGFkYzlmMmY1Mzc2YjM1MjkyZmVkZThjMmQwZWUiLCJ0eXAiOiJKV1QifQ.eyJwcm92aWRlcl9pZCI6ImFub255bW91cyIsImlzcyI6Imh0dHBzOi8vc2VjdXJldG9rZW4uZ29vZ2xlLmNvbS9zdXBlcnRleHQtZDNmMmIiLCJhdWQiOiJzdXBlcnRleHQtZDNmMmIiLCJhdXRoX3RpbWUiOjE2OTM3NTA2OTQsInVzZXJfaWQiOiJMSnU0aFNYc05qT0tOc2VwN1pRUEtjOXQ5ZG4xIiwic3ViIjoiTEp1NGhTWHNOak9LTnNlcDdaUVBLYzl0OWRuMSIsImlhdCI6MTY5MzgzNjEzMywiZXhwIjoxNjkzODM5NzMzLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7fSwic2lnbl9pbl9wcm92aWRlciI6ImFub255bW91cyJ9fQ.Mce2bwUwlOsbVU7CcwPSP-FMLa0HktPyiKU_wfZYXmD95pNbBWhh-FlnU3p7l7iTs4oF7QDcplQ23KNu12PiRLaLRZfuAWG-0Or4wHuUPZQCbJwlKgEWcx4NUpaeqAOeCCaUIml0styDrprGbtm5BxnfTZq0_GpYbM9qSpSC-xQ1hRJya67SJfakznTJeE639xF6yOPd1ORCHgNjIdD46eMzX6BL3YxVSakPEsBkA4ZSYFLYHir5pEcjzF58OaI27I5QQZohERxlHyP9p1t_uECs4_A91P7PlVAZoOrGxIQq-qr1wpE22Lg5hHbUKUP72CEmF9xbguOE1wbVSbTRqw' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: _ga=GA1.1.1131428771.1691937648; g_state={"i_l":0}; _ga_EBJV2RM01B=GS1.1.1693404855.10.1.1693408527.0.0.0; sb-wfapybjfbxvybowxqhul-auth-token-code-verifier=%22ecc0ea765258e0a6360a4f92700fd8a11581cfdd778418a3bee4811aa7a2f70aeace1d2a7b254c5a33a58602598adee5006112a349e9ca3b%22; _ga_F60E9KVFMY=GS1.1.1693754318.8.1.1693754851.0.0.0; _dd_s=rum=0&expire=1693837035646' \
  -H 'Origin: http://localhost:3000' \
  -H 'Referer: http://localhost:3000/' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw '{"data":{"name":"pippo","operation":"create registration challenge"}}' \
  --compressed

Same outcome also if I change the url to the open endpoint https://us-central1-supertext-d3f2b.cloudfunctions.net/ext-firebase-web-authn-api.

Cloud functions are open as you can see calling https://us-central1-supertext-d3f2b.cloudfunctions.net/helloWorld.

gavinsawyer commented 1 year ago

Can I update via npm to 10.1.5?

Yes, I suggest keeping the extension and browser package on the same version. You can do this by running npm i --save-dev @firebase-web-authn/extension@10.1.6 and changing the "@gavinsawyer/firebase-web-authn@X.X.X" reference in firebase.json to "./node_modules/@firebase-web-authn/extension".

I had your "unauthenticated" issue only a few times in testing and it seemed to be while deploying a new version. Redeploying the extension with the same version as the browser package might help.

gavinsawyer commented 1 year ago

I don't see an update button on my console page

Believe it or not I can't upload versions greater than 10. Waiting for an open issue on Firebase Tools and to hear from customer support.

titocosta commented 1 year ago

I tried to reinstall the extension's latest version using the following:

npm i @firebase-web-authn/extension@latest --save-dev
firebase ext:install ./node_modules/@firebase-web-authn/extension
firebase deploy

But still same generic Unauthenticated error both on localhost and at https://supertextnext.vercel.app/

gavinsawyer commented 1 year ago

I noticed your site isn't sending App Check headers. I should update the docs to be more clear regarding this requirement as it not only needs to be set up in the Firebase Console, but should be initialized in your app.

Please call initializeAppCheck at the same time as initializeApp using a reCAPTCHA provider (v3 or Enterprise) on the browser or a generated App Check token on the server. I'm not sure how this works in NextJS but check out my Angular implementation in WebsiteBrowserModule.ts and AppCheckOptionsService.ts

Also, please keep in mind breaking changes on the latest version. When you solve this issue, you may still get an error saying the ext-firebase-web-authn Firestore Database doesn't exist. v10.2.0 changed the Firestore Database used for credentials. This is the new first step after installation:

  1. Create a Firestore Database to store public key credentials with the ID ext-firebase-web-authn and location matching the function deployment. It is recommended to choose either nam5 in North America or eur3 in Europe:

    % firebase firestore:databases:create ext-firebase-web-authn --location ${MULTI_REGION_NAME} --delete-protection ENABLED

If you weren't planning on using App Check and reCAPTCHA, I would consider making enforceAppCheck configurable in a later version.

titocosta commented 1 year ago

I had activated App Check on the firebase console but didn't run initializeAppCheck in the code and that fixed the problem, after creating the firestore database as you suggested.

In case helpful for others, based on recaptcha docs, I also added the following to my root page.tsx to avoid an other error reCAPTCHA placeholder element must be an element or id.

      <button className="g-recaptcha" 
        data-sitekey={process.env.NEXT_PUBLIC_CAPTCHA_KEY}
        data-callback='onSubmit' 
        data-action='submit'>Submit</button>

Thank you.

titocosta commented 1 year ago

Notice also that you should run initializeAppCheck from a useEffect to avoid SSR-related problems in NextJS 13 regarding missing document errors.

gavinsawyer commented 1 year ago

Believe it or not I can't upload versions greater than 10. Waiting for an open issue on Firebase Tools and to hear from customer support.

This issue has been fixed in Firebase Tools v12.5.3 and the latest version of FirebaseWebAuthn is pending review in the Extensions Hub.