How to turn a JWT App into Oauth

Description
I have a JWT app that is working great inside my domain. It connects Zoom attendance data with the Google Apps Script Sheets API. However, I am somewhat new to coding and unsure how to get it so that other users outside the domain can use the same functions. My understanding is that I need to use Oauth rather than JWT.

I have seen the Zoom documentation for Oauth. But I am lost as to how to really implement, especially from the Google Apps Script side. Are there beginner instructions of how Oauth can be set up?

Thanks!

Hey @lgangler,

Thank you for reaching out to the Zoom Developer Forum. If you wanted to make your app available for other users, outside of your account, then an OAuth App is a perfect choice. Once you publish an OAuth app to the marketplace, it can be used by a user outside of your account that authorizes it.

While there isn’t a way to turn a JWT App into an OAuth app, you can use much of your logic, changing the endpoints to reflect the current user instead of account-level scopes.

Google has a toolkit for accessing OAuth services that I’ve linked below. You can potentially use this to authorize with Zoom:

I hope that helps! Let me know if you have any questions.

Thanks,
Max

Thanks @MaxM! I appreciate the info. Right now I am having trouble figuring out paste the //https://zoom.us/oauth/authorize…

Here’s my code:

  function getZoomService() {
  // Create a new service with the given name. The name will be used when
  // persisting the authorized token, so ensure it is unique within the
  // scope of the property store.
  return OAuth2.createService('zoom')

      // Set the endpoint URLs, which are the same for all Google services.
      .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
      .setTokenUrl('https://accounts.google.com/o/oauth2/token')

      // Set the client ID and secret, from the Google Developers Console.
      .setClientId('REDACTED')
      .setClientSecret('REDACTED')

      // Set the name of the callback function in the script referenced
      // above that should be invoked to complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties())

      // Set the scopes to request (space-separated for Google services).
      .setScope('https://www.googleapis.com/auth/drive')

      // Below are Google-specific OAuth2 parameters.

      // Sets the login hint, which will prevent the account chooser screen
      // from being shown to users logged in with multiple accounts.
      .setParam('login_hint', Session.getEffectiveUser().getEmail())

      // Requests offline access.
      .setParam('access_type', 'offline')

      // Consent prompt is required to ensure a refresh token is always
      // returned when requesting offline access.
      .setParam('prompt', 'consent');
}

  
    function showSidebar2() {
     var zoomService = getZoomService();
    if (!zoomService.hasAccess()) {
    var authorizationUrl = zoomService.getAuthorizationUrl();
    var template = HtmlService.createTemplate(
        '<a href="<?= authorizationUrl ?>" target="_blank">Authorize</a>. ' +
        'Reopen the sidebar when the authorization is complete.');
    template.authorizationUrl = authorizationUrl;
    var page = template.evaluate();
    SpreadsheetApp.getUi().showSidebar(page);
  }
}

function authCallback(request) {
  var zoomService = getZoomService();
  var isAuthorized = zoomService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');
  }
}

function makeRequest() {
  var zoomService = getZoomService();
  var response = UrlFetchApp.fetch('https://www.googleapis.com/drive/v2/files?maxResults=10', {
    headers: {
      Authorization: 'Bearer ' + zoomService.getAccessToken()
    }
  });
  // ...
}

Hey @lgangler,

Thank you for the update. Are you able to clarify the issue that you’re having? What errors are you seeing?

I was able to see a couple of issue with the code so far but it mostly seems like this is because you’re using example/documentation values.

When it comes to the following values, you should be using the Authorization URL, Token URL, Client ID, and Client Secret from your Zoom OAuth App.

Also, you won’t need to set the scope when authenticating with the Zoom API:

Last, make sure that you’re setting the parameters that Zoom expects:

Set these instead:

I hope that helps! Let me know if you have any questions.

Thanks,
Max

Thanks, that helps a lot. I am stuck with this error:

Request failed for https://api.zoom.us returned code 400. Truncated server response: {“code”:4700,“message”:“Invalid access token, does not contain scopes: [report:read:admin].”

In the OAuth App Set-up > Scopes the only options under meetings are meeting:read and meeting:write. How do I add the scope that I need for my request?

By the way the request is: https://api.zoom.us/v2/report/meetings/REDACTED/participants?page_size=100

Thanks!

Hey @lgangler,

Thank you for reaching out to the Zoom Developer Forum. Make sure that you’re clicking the Report category of scopes so that you can select the report:read:admin scope.

I hope that helps! Let me know if you have any questions.

Thanks,
Max

Hi @MaxM , thanks for the reply! Does this mean that if an individual user who is not an admin of their domain finds and installs the app in the App Marketplace, they will not be able to use it? I imagine there must be a way to get report data from an individual since the individual could view that in their account anyway. Thanks!

Hey @lgangler,

Good question! As the app would need to be account-level, this means that only an account administrator would be able to install the app. Then, you can use the API to generate reports for any of the users.

We don’t currently have a user-level Report API but if you would like this feature to be considered for a future release, I recommend posting in the #feature-requests category.

Thanks,
Max

Hi @MaxM, thanks for your response! Would there be a way for a domain administrator to give all or some of their users access to an app that requires an admin level scope without actually making them admin in general? I’m trying to think of other workarounds but it seems like I’m hitting a dead end.

Hey @lgangler,

Thank you for your question. While an app is unpublished, users on your account can access it if they have a role with the Marketplace and Developer permissions. You could apply those permissions to another role so that non-admin users can access the app but this would also give them access to build their own apps and edit the JWT app on the account.

Let me know if that helps.

Thanks,
Max