Invalid audience web3auth.io with python-jose

I’m getting “Invalid audience” when trying to verify the token on back-end. I don’t seem to find any documentation how and where should I define intended audience when I generate the token using web3auth.io in front-end. Any suggestions?

Hey @nika

Can you share more details like code snippets, SDK, and its version?

Meanwhile, this link might help. Also, see an example around it in our examples directory.

Hello @shahbaz , thanks for the quick reply. I’m attaching the front-end and back-end code

Front-end - sending token and appPubKey to back-end

        const web3authProvider: any = await web3auth.connect();

        const app_scoped_privkey: any = await web3authProvider.request({
          method: "eth_private_key", // use "private_key" for other non-evm chains
        });
        const app_pub_key = getPublicCompressed(Buffer.from(app_scoped_privkey.padStart(64, "0"), "hex")).toString("hex");

        const user = await web3auth.getUserInfo();

        const res = await fetch("/api/v1/verify_user", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: "Bearer " + user.idToken, // or token.idToken
          },
          body: JSON.stringify({ appPubKey: app_pub_key }),
        });

Back-end - trying to verify the token, but getting “Invalid audience” error

    authorization: str = request.headers.get("Authorization")
    app_pub_key = (await request.json()).get("appPubKey")
    id_token = authorization.split(' ')[1] if authorization else None

    jwks_uri = "https://api.openlogin.com/jwks"
    jwks_data = requests.get(jwks_uri).json()
    jwks_data.get("keys")[0]["alg"] = "ES256"
    data = jwks_data.get("keys")[0]

    jwks = jwk.construct(data)

    jwt_decoded = jwt.decode(id_token, jwks, algorithms=["ES256"])

Hey @nika

Please refer to our implementation of the same in frontend https://github.com/Web3Auth/examples/blob/main/web-no-modal-sdk/server-side-verification/ssv-via-social-nextjs-no-modal-example/pages/App.tsx#L92-L108 and backend https://github.com/Web3Auth/examples/blob/main/web-no-modal-sdk/server-side-verification/ssv-via-social-nextjs-no-modal-example/pages/api/login.ts#L20-L34

@shahbaz my code was practically same as you mentioned, I still changed front-end but still getting same error. When I decode jwt token generated in front-end I see “aud” property which I think might be causing the issue. Please check the screenshot attached, where and why is the “aud” value coming from?

Can you use jose to verify once?

// JWT verification using JWKS

import * as jose from "jose"

// passed from the frontend in the Authorization header
const idToken = req.headers.authorization?.split(' ')[1];

// passed from the frontend in the request body
const app_pub_key = req.body.appPubKey;

// Get the JWK set used to sign the JWT issued by Web3Auth
const jwks = jose.createRemoteJWKSet(new URL("https://api.openlogin.com/jwks"));

// Verify the JWT using Web3Auth's JWKS
const jwtDecoded = await jose.jwtVerify(idToken, jwks, { algorithms: ["ES256"] });

// Checking `app_pub_key` against the decoded JWT wallet's public_key
if ((jwtDecoded.payload as any).wallets[0].public_key === app_pub_key) {
  // Verified
  res.status(200).json({name: 'Verification Successful'})
} else {
  res.status(400).json({name: 'Verification Failed'})
}

@shahbaz With javascript jose it works fine, I can verify the token with this code

        const idToken = req.headers.authorization?.split(' ')[1] || '';
		const app_pub_key = req.body.appPubKey;

		const jwks = jose.createRemoteJWKSet(
			new URL('https://api.openlogin.com/jwks'),
		);
		const jwtDecoded = await jose.jwtVerify(idToken, jwks, {
			algorithms: ['ES256'],
		});
        console.log(jwtDecoded.payload)

The error message was misleading, I see the issue is somewhere in the python code which is supposed to do exactly same thing though. Do you have python example for back-end verification? This is the python code I’m trying to make work

    authorization: str = request.headers.get("Authorization")
    app_pub_key = (await request.json()).get("appPubKey")
    id_token = authorization.split(' ')[1] if authorization else None

    jwks_uri = "https://api.openlogin.com/jwks"
    jwks_data = requests.get(jwks_uri).json()
    jwks_data.get("keys")[0]["alg"] = "ES256"
    data = jwks_data.get("keys")[0]

    jwks = jwk.construct(data)

    jwt_decoded = jwt.decode(id_token, jwks, algorithms=["ES256"])

Thanks for confirming that it works in the Node environment.

Can you try with the below code?

jwks_uri = "https://api.openlogin.com/jwks"
jwks = requests.get(jwks_uri).json()
jwt_decoded = jwt.decode(id_token, jwks, algorithms=["ES256"])

btw which package are you using? python-jose?

@shahbaz yes, I’m using python-jose. Getting same error “invalid audience” with your code:

    authorization: str = request.headers.get("Authorization")
    app_pub_key = (await request.json()).get("appPubKey")
    id_token = authorization.split(' ')[1] if authorization else None

    jwks_uri = "https://api.openlogin.com/jwks"
    jwks = requests.get(jwks_uri).json()
    jwt_decoded = jwt.decode(id_token, jwks.get("keys")[0], algorithms=["ES256"])

@shahbaz disabling verify audience did the trick. Thank you so much for helping out. Here is the final code that worked:

Front-end javascript:

        const web3authProvider: any = await web3auth.connect();
        const { idToken } = await web3auth.authenticateUser();

        const privKey: any = await web3auth.provider?.request({
          method: "eth_private_key",
        });
        const pubkey = getPublicCompressed(Buffer.from(privKey, "hex")).toString("hex");

        const res = await fetch("/api/v1/verify_user", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            Authorization: `Bearer ${idToken}`,
          },
          body: JSON.stringify({ appPubKey: pubkey }),
        });

Back-end python/python-jose:

    authorization: str = request.headers.get("Authorization")
    app_pub_key = (await request.json()).get("appPubKey")
    id_token = authorization.split(' ')[1] if authorization else None

    jwks_uri = "https://api.openlogin.com/jwks"
    jwks = requests.get(jwks_uri).json()
    jwt_decoded = jwt.decode(id_token, jwks.get("keys")[0], algorithms=["ES256"], options={'verify_aud': False})
1 Like

Thank you @nika for sharing the final code with the community.

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