Better Auth Passkeys working locally but not on Vercel

On my NextJS project I’ve configured the better-auth passkey plugin. Locally, through my browser (Firefox/Chrome) I can add a passkey, but not in production on Vercel. I’m using a simple button in NextJS to trigger adding a passkey:

const { data, error } = await authClient.passkey.addPasskey();

Which locally, prompts my browser (Firefox or Chrome) to a add a passkey:

However, in production on Vercel, I see the GET request to the endpoint in my browser:

https://api.mysite.com/v1/auth/passkey/generate-register-options 200 OK

And the response looks ok (I think?):

{
    "challenge": "4ShVg5WW5XJRuw_2RLFzfcDuzOjt_vix5ZwXUR761qQ",
    "rp": {
        "name": "My App",
        "id": "api.mysite.com"
    },
    "user": {
        "id": "aWt4OWt0aHMzbXlreXZpMXc5Z3FrdHp4eGpxZW92cTA",
        "name": "colin@mysite.com",
        "displayName": ""
    },
    "pubKeyCredParams": [
        {
            "alg": -8,
            "type": "public-key"
        },
        {
            "alg": -7,
            "type": "public-key"
        },
        {
            "alg": -257,
            "type": "public-key"
        }
    ],
    "timeout": 60000,
    "attestation": "none",
    "excludeCredentials": [],
    "authenticatorSelection": {
        "residentKey": "preferred",
        "userVerification": "preferred",
        "requireResidentKey": false
    },
    "extensions": {
        "credProps": true
    },
    "hints": []
}

But the browser prompt to add the passkey doesn’t trigger/appear. And there’s no subsequent /passkey/verify-registration POST request as there is locally.

I can’t figure out what the issue could be as I’m not seeing any errors in my browser or Vercel’s logs.

I’m wondering if there’s something specific to Vercel’s platform I might be missing?

Any help on where to start debugging this would be appreciated. :folded_hands:

Hey @colinwilson
Thanks for post here, I find this interesting! (also absolutely dig the profile pic!) :grinning_cat:

Typically when I see something like this work on local but not deployed, it is usually some sort of configuration step that is either missing or incorrect.

Sometimes I see this when there typo or missing environment variable like a AUTH_DOMAIN or AUTH_ORIGIN where it is empty or set to "localhost" instead of your domain. However it seems you are getting at least the initial GET to trigger the start of the flow.

I’d love a confirmation that the environment seems good, and happy to dig further.

Are the auth routes in the Next application? or do you have a separate project/api outside of the application?

Thank you! Your hint helped me resolve the issue.

The plugin’s rpID option was configured wrong.

I primarily use FireFox for development, so don’t check stuff in Chrome as often as I should. When sending the request to my api endpoint in Chrome I received the following error:

[Fido2Client] 'rp.id' cannot be used with the current origin: rp.id = api.mysite.com; origin = 'https://dash.mysite.com'

(I didn’t see any errors of the sort in Firefox! :-1:)

My development / localhost value for rpID was localhost:3000.

So I updated the rpID value to mysite.com for production (Vercel). Et Voila! The passkey prompt is now triggered in all browsers (Firefox, Chrome, Safari).

Thanks again for pointing me in the right direction. :+1: Much appreciated.

P.S. Glad you like my profile pic :grinning_cat_with_smiling_eyes:

2 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.