title: Add Redirect URI To Automatically Generated Google OAuth 2.0 Client ID
body: <p>I'm trying to make a Google sheet that integrates with the YouTube Data and Analytics API. However, when trying to implement this, I came into a known issue with regards to allowing brand YouTube accounts/channels to be authenticated with a Google app which is explained here. <a href="https://issuetracker.google.com/issues/36764531" rel="nofollow noreferrer">https://issuetracker.google.com/issues/36764531</a></p>
  <p>To get around this, the document mentions instructions from this link which I am now trying to implement myself <a href="https://mashe.hawksey.info/2017/09/identity-crisis-using-the-youtube-api-with-google-apps-script-and-scheduling-live-broadcasts-from-google-sheets/" rel="nofollow noreferrer">https://mashe.hawksey.info/2017/09/identity-crisis-using-the-youtube-api-with-google-apps-script-and-scheduling-live-broadcasts-from-google-sheets/</a></p>
  <p>From the instructions, I have:</p>
  <ol>
  <li>Imported the necessary libraries into the script</li>
  <li>Added the necessary Google Apps Script code which is at the bottom</li>
  <li>Created my own OAuth 2.0 Client ID credentials in the Google Cloud Console</li>
  </ol>
  <p>However, in the first link, a comment had also been added to say that while the instructions still worked, the script project now has to be associated with a cloud project and so that's what I did. As part of this, it created its own OAuth 2.0 Client ID which I believe it's now using rather than the credentials I had already generated myself. I have added a picture below to illustrate what I mean. I also then can't edit these new credentials meaning that I can't add any redirect URI.</p>
  <p><a href="https://i.stack.imgur.com/9QYZ4.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/9QYZ4.png" alt="enter image description here" /></a></p>
  <p>Is there a way I can add the redirect URI to the automatically generated credentials? The problem now is that if I then run the setup function from the script as per the instructions, when I then try to open this link it gives me, I then get given the following message</p>
  <p><strong>Error 400: redirect_uri_mismatch</strong></p>
  <p>The redirect URI in the request, <a href="https://script.google.com/macros/d/12u2laknmO_9-zgxBbAX6wG9gJDUOvgJmYm5UquJsamShus9s5McrGBar/usercallback" rel="nofollow noreferrer">https://script.google.com/macros/d/12u2laknmO_9-zgxBbAX6wG9gJDUOvgJmYm5UquJsamShus9s5McrGBar/usercallback</a>, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs, visit: <a href="https://console.developers.google.com/apis/credentials/oauthclient/$%7Byour_client_id%7D?project=$%7Byour_project_number%7D" rel="nofollow noreferrer">https://console.developers.google.com/apis/credentials/oauthclient/${your_client_id}?project=${your_project_number}</a></p>
  <pre><code>/**
   * Authorizes and makes a request to the YouTube Data API.
   */
  function setup() {
    var service = getYouTubeService();
    YouTube.setTokenService(function(){ return service.getAccessToken(); });
    if (service.hasAccess()) {
      var result = YouTube.channelsList(&quot;snippet&quot;, {mine:true});
      Logger.log(JSON.stringify(result, null, 2));
      throw &quot;Open View &gt; Logs to see result&quot;;
    } else {
      var authorizationUrl = service.getAuthorizationUrl();
      Logger.log('Open the following URL and re-run the script: %s',
          authorizationUrl);
      throw &quot;Open View &gt; Logs to get authentication url&quot;;
    }
  }
   
   
  /**
   * Configures the service.
   */
  function getYouTubeService() {
    return OAuth2.createService('YouTube')
        // Set the endpoint URLs.
        .setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
        .setTokenUrl('https://accounts.google.com/o/oauth2/token')
   
        // Set the client ID and secret.
        .setClientId(getStaticScriptProperty_('client_id'))
        .setClientSecret(getStaticScriptProperty_('client_secret'))
   
        // Set the name of the callback function that should be invoked to complete
        // the OAuth flow.
        .setCallbackFunction('authCallback')
   
        // Set the property store where authorized tokens should be persisted
        // you might want to switch to Script Properties if sharing access
        .setPropertyStore(PropertiesService.getUserProperties())
   
        // Set the scope and additional Google-specific parameters.
        .setScope([&quot;https://www.googleapis.com/auth/youtube&quot;,
        &quot;https://www.googleapis.com/auth/youtube.force-ssl&quot;,
        &quot;https://www.googleapis.com/auth/youtube.readonly&quot;,
        &quot;https://www.googleapis.com/auth/youtubepartner&quot;,
        &quot;https://www.googleapis.com/auth/youtubepartner-channel-audit&quot;])
        .setParam('access_type', 'offline');
  }
   
  /**
   * Handles the OAuth callback.
   */
  function authCallback(request) {
    var service = getYouTubeService();
    var authorized = service.handleCallback(request);
    if (authorized) {
      return HtmlService.createHtmlOutput('Success!');
    } else {
      return HtmlService.createHtmlOutput('Denied');
    }
  }
   
  /**
   * Logs the redirect URI to register in the Google Developers Console.
   */
  function logRedirectUri() {
    var service = getYouTubeService();
    Logger.log(service.getRedirectUri());
    throw &quot;Open View &gt; Logs to get redirect url&quot;;
  }
   
  /**
   * Reset the authorization state, so that it can be re-tested.
   */
  function reset() {
    var service = getYouTubeService();
    service.reset();
  }
   
  /**
   * Gets a static script property, using long term caching.
   * @param {string} key The property key.
   * @returns {string} The property value.
   */
  function getStaticScriptProperty_(key) {
    var value = CacheService.getScriptCache().get(key);
    if (!value) {
      value = PropertiesService.getScriptProperties().getProperty(key);
      CacheService.getScriptCache().put(key, value, 21600);
    }
    return value;
  }
  </code></pre>
  <p>I hope this is clear but if not then I can answer any further questions. Or if there is a better way of being able to authenticate a brand YouTube account with the API, then please let me know.</p>