Search code examples
google-apps-scriptoauthstackexchange-api

How to set the redirect uri in the stack overflow rest api


I am trying to authorize google app script to the stack overflow rest api.

My script asks me to open the authorization window and everything looks good from there except after I have authorized the app I get.

redirect_uri is not under the registered domain for this application

The redirect URI app script is creating is as follows.

https://script.google.com/macros/d/1iGFdsYBrkOTRYdyv0A81xITdFetvhfxcR_s_3iOj0dyds_Zbk1wzGAG9/usercallback

I have searched all over and I cant seem to figure out how to configure the redirect uri in my client for stack overflow API.

enter image description here


Solution

  • stackApps side:

    In your situation, please set the Stackoverflow side as follows.

    • OAuth Domain is script.google.com.
    • Application Website is https://script.google.com/macros/d/1iGFdsYBrkOTRYdyv0A81xITdFetvhfxcR_s_3iOj0dyds_Zbk1wzGAG9/usercallback.

    Google Apps Script side:

    Please modify your script as follows.

    From:

    var tokenExchangeUrl = "https://stackoverflow.com/oauth/access_token"
    

    To:

    var tokenExchangeUrl = "https://stackoverflow.com/oauth/access_token/json"
    

    And, in your script, the scope is not included. So, please modify getService_() as follows.

    function getService_() {
      return OAuth2.createService('StackOverflow')
          // Set the endpoint URLs.
          .setAuthorizationBaseUrl(authorizationUrl)
          .setTokenUrl(tokenExchangeUrl)
          .setScope(scope) // Added
    
          // Set the client ID and secret.
          .setClientId(CLIENT_ID)
          .setClientSecret(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.
          .setPropertyStore(PropertiesService.getUserProperties());
    }
    

    And, I think that the sample request is required to be modified. So, how about the following sample?

    From:

    var url = authorizationUrl;
    
    
    var response = UrlFetchApp.fetch(url, {
      headers: {
        'Authorization': 'Bearer ' + service.getAccessToken()
      }
    });
    

    To:

    var url = `https://api.stackexchange.com/2.3/me/inbox?site=stackoverflow&key=${key}&access_token=${service.getAccessToken()}`;
    var response = UrlFetchApp.fetch(url);
    
    • By this modification, the access token can be retrieved and the inbox can be retrieved using the access token.

    Note:

    • As additional information, the whole modified script is as follows.

    var CLIENT_ID = [REDACTED];
    var CLIENT_SECRET = [REDACTED]
    var key = [REDACTEd]
    
    var authorizationUrl = "https://stackoverflow.com/oauth"
    var tokenExchangeUrl = "https://stackoverflow.com/oauth/access_token/json"
    var scope = "read_inbox"
    
    /**
     * Authorizes and makes a request to the Stackoverflow API.
     */
    function run() {
      var service = getService_();
      console.log(service.getRedirectUri())
      if (service.hasAccess()) {
        var url = `https://api.stackexchange.com/2.3/me/inbox?site=stackoverflow&key=${key}&access_token=${service.getAccessToken()}`;
        var response = UrlFetchApp.fetch(url);
        var result = JSON.parse(response.getContentText());
        Logger.log(JSON.stringify(result, null, 2));
      } else {
        var authorizationUrl = service.getAuthorizationUrl();
        Logger.log('Open the following URL and re-run the script: %s',
            authorizationUrl);
      }
    }
    
    /**
     * Reset the authorization state, so that it can be re-tested.
     */
    function reset() {
      getService_().reset();
    }
    
    /**
     * Configures the service.
     */
    function getService_() {
      return OAuth2.createService('StackOverflow')
          // Set the endpoint URLs.
          .setAuthorizationBaseUrl(authorizationUrl)
          .setTokenUrl(tokenExchangeUrl)
          .setScope(scope)
    
          // Set the client ID and secret.
          .setClientId(CLIENT_ID)
          .setClientSecret(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.
          .setPropertyStore(PropertiesService.getUserProperties());
    }
    
    /**
     * Handles the OAuth callback.
     */
    function authCallback(request) {
      var service = getService_();
      var authorized = service.handleCallback(request);
      if (authorized) {
        return HtmlService.createHtmlOutput('Success!');
      } else {
        return HtmlService.createHtmlOutput('Denied.');
      }
    }
    
    /**
     * Logs the redict URI to register.
     */
    function logRedirectUri() {
      Logger.log(OAuth2.getRedirectUri());
    }

    Reference: