Convex Web3Auth

Hello, i am working on integrating web3auth with convex, the issue seems that when i pass the identity token generated after they login with socials/metamask

it doesnt contain any sub field and thus making the token invalid since convex

Custom JWTs are required only to have header fields kid , alg and typ , and payload fields sub , iss , and exp . An iat field is also expected by Convex clients to implement token refreshing.

Currently using next to connect

const { connect, loading: connectLoading, error: connectError } = useWeb3AuthConnect();
await connect();
const newToken = await getIdentityToken();

ideally would want the identityToken to include this field

Thank you for providing detailed context about your integration with Convex and Web3Auth.

Summary of Your Issue:

  • SDK: Web3Auth Plug and Play (React, using @web3auth/modal)
  • Platform: Next.js (React)
  • Integration Target: Convex (requires JWTs with sub, iss, exp, iat)
  • Problem: The identity token (idToken) generated by Web3Auth after login (socials/MetaMask) does not contain the sub field, making it invalid for Convex, which expects sub, iss, exp, and iat in the JWT payload.

What We Know:

  • You are using the standard Web3Auth login flow:
    const { connect, loading: connectLoading, error: connectError } = useWeb3AuthConnect();
    await connect();
    const newToken = await getIdentityToken();
    
  • The JWT returned by getIdentityToken does not have the sub claim, which Convex expects.

What Convex Requires in JWT Payload:

  • header: kid, alg, typ
  • payload: sub, iss, exp, iat

What Web3Auth Provides:

  • For social logins: JWT payload typically includes iat, aud, iss, email, name, verifier, verifierId, exp, wallets, etc. (see Web3Auth Docs - getIdentityToken)
  • For external wallets: JWT payload includes iat, issuer, audience, wallets, exp, etc.

Possible Causes & Next Steps:

  • The JWT from Web3Auth may use verifierId or another field instead of sub.
  • Some JWTs (especially from social logins) may not include sub by default.
  • Convex expects sub for user identification.

Proposed Solution / Next Steps:

  1. Check the Decoded JWT:
    Please decode the idToken (using jwt.io or similar) and paste the payload here (you can redact sensitive info). This will help confirm which fields are present and if sub is missing or mapped differently (e.g., verifierId).

  2. If sub is missing:

    • Web3Auth currently does not provide a way to customize the JWT payload directly in Plug n Play mode.
    • You may need to map verifierId or another unique identifier from the JWT to sub on your backend before passing it to Convex.
    • Alternatively, you can submit a feature request for Web3Auth to add sub to the JWT payload for better compatibility with Convex.
  3. Reference Documentation:

Questions for You (if you can provide):

  • Can you share a sample decoded JWT payload (with sensitive info redacted)?
  • Are you using only Plug n Play (no custom authentication or verifiers)?

Summary for Support Team:

  • User is integrating Web3Auth Plug n Play (React/Next.js) with Convex.
  • The JWT idToken generated after login lacks the sub field required by Convex.
  • User needs either a way to include sub in the JWT or guidance on mapping an existing JWT field to sub.

Let us know if you can share the JWT payload, or if you need guidance on mapping fields for Convex compatibility!

Note: This response was generated by an AI bot and may require further verification. The Web3Auth support team has tracked this issue and will be responding as soon as possible.

Additionally, we would recommend you to join our biweekly Office Hours to get this resolved even faster. Web3Auth Developer Office Hours

{
“iat”: 1755712635,
“aud”: “my-client-id”,
“nonce”: “030e1bb8fbcd8a3ca66aaefe247bff8d25b7a0a1231d0ee888f79b950fb1ca182c”,
“iss”: “https://api-auth.web3auth.io”,
“wallets”: [
{
“public_key”: “d07c504a122e8439583a6f13c1eff8f02e482e8902e998e76988b63727aad4aa”,
“type”: “web3auth_app_key”,
“curve”: “ed25519”
},
{
“public_key”: “3b045acdcc48ef5165413c455878c72ece6c450138e2748ab81b492dce3cb640”,
“type”: “web3auth_threshold_key”,
“curve”: “ed25519”
},
{
“public_key”: “039543c8e4e1bd3b595b4a0960a24f4442493ea74f40a42575707f988236bb7b25”,
“type”: “web3auth_app_key”,
“curve”: “secp256k1”
},
{
“public_key”: “0331465ebc069dc26ddf5f3b85e25a9543a78312b030bb81afb1d6ea1b23f341e5”,
“type”: “web3auth_threshold_key”,
“curve”: “secp256k1”
}
],
“email”: “myemail@gmail.com”,
“name”: “MyFullName”,
“profileImage”: “https://lh3.googleusercontent.com/a/ACg8ocLnQGuwv-7AtAh1tX9L9sKfab--olbuZ3zflANnCa6S01vnFO8=s96-c”,
“verifier”: “web3auth”,
“authConnectionId”: “web3auth”,
“verifierId”: “myemail@gmail.com”,
“userId”: “myemail@gmail.com”,
“aggregateVerifier”: “web3auth-google-sapphire-devnet”,
“groupedAuthConnectionId”: “web3auth-google-sapphire-devnet”,
“exp”: 1755799035
}

im only using the plug n play