Dont understand how to fetch the authenticated zoom user

Zoom Apps Configuration
Zoom App SDK
React , Nodejs , Express


I am using the zoom react advanced sample as a reference but struggling to understand how to fetch the logged in user/token when an already authorized user opens the app.

So If I understand correctly the /home route is called when the app is launched since that’s the home URL.

Then that route decrypts the header x-zoom-app-context which gets the decrypted token in order to get the user.

So that’s great. BUT

We have a separate React app deployed on Firebase at the moment and an API deployed elsewhere.
Is it possible to capture that header without doing a proxy through the API?

@heinrich With the latest version of the Zoom Apps SDK, we have the getAppContext() function that will provide the client with the same Zoom Apps Context Header as when using a server.

Let me know if that helps.

@MaxM Thanks for that answer. It really helped push me in the right direction.

So I get the context, pass it to the api, decrypt it and get the zoom user.


This worked the first time and then got invalid token.

So my question is, do you need to do the Auth challenge and then onauthorized event to refresh the token?

My problem is for some reason req.session.codeVerifier for example is not persisting, so I call authorize to generate the state and the codeVerifier but then wehen onauthorized fires of the endpoint, I dont know what the codeChallenge was.

I recommend checking out our Advanced Sample App which has a great example of using in-client OAuth. It uses an endpoint that generates the state and challenge and sends them to the client:

I recently wrote an example showing how you can use in-client and browser-based OAuth where you are checking your DB for an existing user token before proceeding with in-client auth.

In this instance, I am also generating the state and Challenge server-side and including them in the response to the client.


import zoomSdk from '@zoom/appssdk';

async function authorize() {
    try {
        // Use the SDK function to read getAppContext()
        const {context} = await zoomSdk.getAppContext();

        // Check if we have authorized this UID yet
        let response = await fetch(`/auth/check`, {
            method: 'POST',
            mode: 'cors',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({context})
        let {hasAuth} = await response.json();

        // skip the authorization if this user has already been authorized
        if (hasAuth) return console.log('existing authorization found');

        // generate unique tokens for PKCE and store them in the session
        response = await fetch(`/auth/authorize`);
        const { state, challenge } = await response.json()

        // Authorize the app in-client
        await zoomSdk.authorize({
            state: state,
            codeChallenge: challenge
    } catch (e) {
        return console.log(e);

(async () => {
    try {
        const configResponse = await zoomSdk.config({
            size: {width: 480, height: 360},
            capabilities: [

        console.debug('Zoom JS SDK Configuration', configResponse);

        const authBtn = document.getElementById('authBtn');
        authBtn.addEventListener('click', authorize);

        zoomSdk.onAuthorized(async (e) => {
            const {code, state} = e;

            // complete the OAuth flow to get the token
            await fetch(
                `/auth?${new URLSearchParams({
                    isClient: true,
    } catch (e) {