Google Workspace অ্যাড-অন থেকে নন-Google পরিষেবার সাথে কানেক্ট করা

আপনার Google Workspace অ্যাড-অন প্রোজেক্ট অ্যাপ স্ক্রিপ্টের বিল্ট-ইন এবং উন্নত পরিষেবার সাহায্যে অনেক Google প্রোডাক্টের সাথে সরাসরি কানেক্ট করতে পারে।

এছাড়াও আপনি নন-Google API এবং পরিষেবাগুলি অ্যাক্সেস করতে পারেন৷ পরিষেবাটির অনুমোদনের প্রয়োজন না হলে, আপনি সাধারণত একটি উপযুক্ত UrlFetch অনুরোধ করতে পারেন এবং তারপরে আপনার অ্যাড-অনকে প্রতিক্রিয়া ব্যাখ্যা করতে পারেন।

যাইহোক, যদি নন-Google পরিষেবার অনুমোদনের প্রয়োজন হয়, তাহলে আপনাকে অবশ্যই সেই পরিষেবার জন্য OAuth কনফিগার করতে হবে। আপনি Apps স্ক্রিপ্ট লাইব্রেরির জন্য OAuth2 ব্যবহার করে এই প্রক্রিয়াটিকে আরও সহজ করতে পারেন (এছাড়াও একটি OAuth1 সংস্করণ রয়েছে)।

একটি OAuth পরিষেবা ব্যবহার করা

Google-এর বাইরের পরিষেবার সাথে কানেক্ট করার জন্য OAuth পরিষেবার অবজেক্ট ব্যবহার করার সময়, আপনার Google Workspace অ্যাড-অনকে শনাক্ত করতে হবে কখন অনুমোদনের প্রয়োজন হবে এবং যখন এটি হবে তখন অনুমোদনের ফ্লো শুরু করতে হবে।

অনুমোদন প্রবাহের মধ্যে রয়েছে:

  1. ব্যবহারকারীকে সতর্ক করে যে প্রমাণীকরণ প্রয়োজন এবং প্রক্রিয়া শুরু করার জন্য একটি লিঙ্ক প্রদান করে।
  2. নন-Google পরিষেবা থেকে অনুমোদন নেওয়া।
  3. সুরক্ষিত সংস্থান অ্যাক্সেস করার জন্য পুনরায় চেষ্টা করতে অ্যাড-অন রিফ্রেশ করা হচ্ছে।

যখন নন-Google অনুমোদনের প্রয়োজন হয়, তখন Google Workspace অ্যাড-অন পরিকাঠামো এই বিবরণগুলি পরিচালনা করে। আপনার অ্যাড-অন শুধুমাত্র সনাক্ত করতে হবে যখন অনুমোদনের প্রয়োজন হয় এবং যখন প্রয়োজন হয় তখন অনুমোদনের প্রবাহ শুরু করতে হবে।

যে অনুমোদন প্রয়োজন সনাক্ত করা

একটি অনুরোধের বিভিন্ন কারণে একটি সুরক্ষিত সম্পদ অ্যাক্সেস করার অনুমোদন নাও থাকতে পারে, যেমন:

  • অ্যাক্সেস টোকেন এখনও তৈরি করা হয়নি বা মেয়াদ শেষ হয়েছে।
  • অ্যাক্সেস টোকেন অনুরোধ করা সংস্থান কভার করে না।
  • অ্যাক্সেস টোকেন অনুরোধের প্রয়োজনীয় সুযোগগুলিকে কভার করে না।

আপনার অ্যাড-অন কোড এই ক্ষেত্রে সনাক্ত করা উচিত. OAuth লাইব্রেরি hasAccess() ফাংশন আপনাকে বলতে পারে যে আপনার বর্তমানে কোনো পরিষেবাতে অ্যাক্সেস আছে কিনা। বিকল্পভাবে, UrlFetchApp fetch() অনুরোধগুলি ব্যবহার করার সময়, আপনি muteHttpExceptions প্যারামিটারটিকে true এ সেট করতে পারেন। এটি অনুরোধ ব্যর্থতার জন্য একটি ব্যতিক্রম ছুঁড়ে দেওয়া থেকে অনুরোধকে বাধা দেয় এবং আপনাকে ফিরে আসা HttpResponse অবজেক্টে অনুরোধের প্রতিক্রিয়া কোড এবং বিষয়বস্তু পরীক্ষা করার অনুমতি দেয়।

যখন অ্যাড-অন সনাক্ত করে যে অনুমোদনের প্রয়োজন, তখন এটি অনুমোদনের প্রবাহকে ট্রিগার করবে।

অনুমোদন প্রবাহ আহ্বান

আপনি একটি AuthorizationException অবজেক্ট তৈরি করতে, এর বৈশিষ্ট্যগুলি সেট করতে এবং তারপর throwException() ফাংশনটি কল করার জন্য কার্ড পরিষেবা ব্যবহার করে অনুমোদনের প্রবাহ শুরু করেন। ব্যতিক্রম নিক্ষেপ করার আগে, আপনি নিম্নলিখিত প্রদান করুন:

  1. প্রয়োজন। একটি অনুমোদন URL। এটি নন-Google পরিষেবা দ্বারা নির্দিষ্ট করা হয় এবং অনুমোদনের প্রবাহ শুরু হলে ব্যবহারকারীকে যেখানে নিয়ে যাওয়া হয়। আপনি setAuthorizationUrl() ফাংশন ব্যবহার করে এই URL সেট করেছেন।
  2. প্রয়োজন। একটি সম্পদ প্রদর্শন নামের স্ট্রিং। অনুমোদনের অনুরোধ করা হলে ব্যবহারকারীর কাছে সংস্থান সনাক্ত করে। আপনি setResourceDisplayName() ফাংশন ব্যবহার করে এই নামটি সেট করেছেন।
  3. একটি কলব্যাক ফাংশনের নাম যা একটি কাস্টম অনুমোদন প্রম্পট তৈরি করে। এই কলব্যাকটি বিল্ট Card অবজেক্টের একটি অ্যারে প্রদান করে যা অনুমোদন পরিচালনার জন্য একটি UI রচনা করে। এটি ঐচ্ছিক; সেট না হলে ডিফল্ট অনুমোদন কার্ড ব্যবহার করা হয়। আপনি setCustomUiCallback() ফাংশন ব্যবহার করে কলব্যাক ফাংশন সেট করেন।

নন-Google OAuth কনফিগারেশনের উদাহরণ

এই কোড নমুনাটি দেখায় যে কীভাবে একটি অ্যাড-অন কনফিগার করতে হয় একটি নন-Google API ব্যবহার করতে যাতে OAuth প্রয়োজন হয়৷ এটি API অ্যাক্সেস করার জন্য একটি পরিষেবা তৈরি করতে Apps স্ক্রিপ্টের জন্য OAuth2 ব্যবহার করে।

/**
 * Attempts to access a non-Google API using a constructed service
 * object.
 *
 * If your add-on needs access to non-Google APIs that require OAuth,
 * you need to implement this method. You can use the OAuth1 and
 * OAuth2 Apps Script libraries to help implement it.
 *
 * @param {String} url         The URL to access.
 * @param {String} method_opt  The HTTP method. Defaults to GET.
 * @param {Object} headers_opt The HTTP headers. Defaults to an empty
 *                             object. The Authorization field is added
 *                             to the headers in this method.
 * @return {HttpResponse} the result from the UrlFetchApp.fetch() call.
 */
function accessProtectedResource(url, method_opt, headers_opt) {
  var service = getOAuthService();
  var maybeAuthorized = service.hasAccess();
  if (maybeAuthorized) {
    // A token is present, but it may be expired or invalid. Make a
    // request and check the response code to be sure.

    // Make the UrlFetch request and return the result.
    var accessToken = service.getAccessToken();
    var method = method_opt || 'get';
    var headers = headers_opt || {};
    headers['Authorization'] =
        Utilities.formatString('Bearer %s', accessToken);
    var resp = UrlFetchApp.fetch(url, {
      'headers': headers,
      'method' : method,
      'muteHttpExceptions': true, // Prevents thrown HTTP exceptions.
    });

    var code = resp.getResponseCode();
    if (code >= 200 && code < 300) {
      return resp.getContentText("utf-8"); // Success
    } else if (code == 401 || code == 403) {
       // Not fully authorized for this action.
       maybeAuthorized = false;
    } else {
       // Handle other response codes by logging them and throwing an
       // exception.
       console.error("Backend server error (%s): %s", code.toString(),
                     resp.getContentText("utf-8"));
       throw ("Backend server error: " + code);
    }
  }

  if (!maybeAuthorized) {
    // Invoke the authorization flow using the default authorization
    // prompt card.
    CardService.newAuthorizationException()
        .setAuthorizationUrl(service.getAuthorizationUrl())
        .setResourceDisplayName("Display name to show to the user")
        .throwException();
  }
}

/**
 * Create a new OAuth service to facilitate accessing an API.
 * This example assumes there is a single service that the add-on needs to
 * access. Its name is used when persisting the authorized token, so ensure
 * it is unique within the scope of the property store. You must set the
 * client secret and client ID, which are obtained when registering your
 * add-on with the API.
 *
 * See the Apps Script OAuth2 Library documentation for more
 * information:
 *   https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
 *
 *  @return A configured OAuth2 service object.
 */
function getOAuthService() {
  return OAuth2.createService('SERVICE_NAME')
      .setAuthorizationBaseUrl('SERVICE_AUTH_URL')
      .setTokenUrl('SERVICE_AUTH_TOKEN_URL')
      .setClientId('CLIENT_ID')
      .setClientSecret('CLIENT_SECRET')
      .setScope('SERVICE_SCOPE_REQUESTS')
      .setCallbackFunction('authCallback')
      .setCache(CacheService.getUserCache())
      .setPropertyStore(PropertiesService.getUserProperties());
}

/**
 * Boilerplate code to determine if a request is authorized and returns
 * a corresponding HTML message. When the user completes the OAuth2 flow
 * on the service provider's website, this function is invoked from the
 * service. In order for authorization to succeed you must make sure that
 * the service knows how to call this function by setting the correct
 * redirect URL.
 *
 * The redirect URL to enter is:
 * https://script.google.com/macros/d/<Apps Script ID>/usercallback
 *
 * See the Apps Script OAuth2 Library documentation for more
 * information:
 *   https://github.com/googlesamples/apps-script-oauth2#1-create-the-oauth2-service
 *
 *  @param {Object} callbackRequest The request data received from the
 *                  callback function. Pass it to the service's
 *                  handleCallback() method to complete the
 *                  authorization process.
 *  @return {HtmlOutput} a success or denied HTML message to display to
 *          the user. Also sets a timer to close the window
 *          automatically.
 */
function authCallback(callbackRequest) {
  var authorized = getOAuthService().handleCallback(callbackRequest);
  if (authorized) {
    return HtmlService.createHtmlOutput(
      'Success! <script>setTimeout(function() { top.window.close() }, 1);</script>');
  } else {
    return HtmlService.createHtmlOutput('Denied');
  }
}

/**
 * Unauthorizes the non-Google service. This is useful for OAuth
 * development/testing.  Run this method (Run > resetOAuth in the script
 * editor) to reset OAuth to re-prompt the user for OAuth.
 */
function resetOAuth() {
  getOAuthService().reset();
}

একটি কাস্টম অনুমোদন প্রম্পট তৈরি করা হচ্ছে

নন-Google পরিষেবা অনুমোদন কার্ড

ডিফল্টরূপে, একটি অনুমোদনের প্রম্পটে কোনো ব্র্যান্ডিং থাকে না এবং অ্যাড-অনটি কোন রিসোর্সটি অ্যাক্সেস করার চেষ্টা করছে তা নির্দেশ করার জন্য শুধুমাত্র প্রদর্শন নামের স্ট্রিং ব্যবহার করে। আপনার অ্যাড-অন, তবে, একটি কাস্টমাইজড অনুমোদন কার্ড সংজ্ঞায়িত করতে পারে যা একই উদ্দেশ্যে কাজ করে এবং অতিরিক্ত তথ্য এবং ব্র্যান্ডিং অন্তর্ভুক্ত করতে পারে।

আপনি একটি কাস্টম UI কলব্যাক ফাংশন প্রয়োগ করে একটি কাস্টম প্রম্পট সংজ্ঞায়িত করেন যা বিল্ট Card অবজেক্টের একটি অ্যারে প্রদান করে। এই অ্যারেতে শুধুমাত্র একটি কার্ড থাকা উচিত। আরো প্রদান করা হলে, তাদের শিরোনাম একটি তালিকায় প্রদর্শিত হয়, যার ফলে ব্যবহারকারীর অভিজ্ঞতা বিভ্রান্তিকর হতে পারে।

ফিরে আসা কার্ডটি অবশ্যই নিম্নলিখিতগুলি করতে হবে:

  • ব্যবহারকারীকে এটা পরিষ্কার করে দিন যে অ্যাড-অনটি তাদের তরফে একটি নন-Google পরিষেবা অ্যাক্সেস করার অনুমতি চাইছে।
  • অনুমোদিত হলে অ্যাড-অনটি কী করতে সক্ষম তা স্পষ্ট করুন।
  • একটি বোতাম বা অনুরূপ উইজেট রয়েছে যা ব্যবহারকারীকে পরিষেবার অনুমোদন URL-এ নিয়ে যায়৷ নিশ্চিত করুন যে এই উইজেটের কার্যকারিতা ব্যবহারকারীর কাছে স্পষ্ট।
  • অনুমোদন প্রাপ্তির পরে অ্যাড-অন পুনরায় লোড নিশ্চিত করতে উপরের উইজেটটিকে তার OpenLink অবজেক্টে OnClose.RELOAD_ADD_ON সেটিংস ব্যবহার করতে হবে।
  • অনুমোদন প্রম্পট থেকে খোলা সমস্ত লিঙ্ক অবশ্যই HTTPS ব্যবহার করবে

আপনি আপনার AuthorizationException অবজেক্টে setCustomUiCallback() ফাংশন কল করে আপনার কার্ড ব্যবহার করার জন্য অনুমোদনের প্রবাহকে নির্দেশ করুন।

নিম্নলিখিত উদাহরণটি একটি কাস্টম অনুমোদন প্রম্পট কলব্যাক ফাংশন দেখায়:

/**
 * Returns an array of cards that comprise the customized authorization
 * prompt. Includes a button that opens the proper authorization link
 * for a non-Google service.
 *
 * When creating the text button, using the
 * setOnClose(CardService.OnClose.RELOAD_ADD_ON) function forces the add-on
 * to refresh once the authorization flow completes.
 *
 * @return {Card[]} The card representing the custom authorization prompt.
 */
function create3PAuthorizationUi() {
  var service = getOAuthService();
  var authUrl = service.getAuthorizationUrl();
  var authButton = CardService.newTextButton()
      .setText('Begin Authorization')
      .setAuthorizationAction(CardService.newAuthorizationAction()
          .setAuthorizationUrl(authUrl));

  var promptText =
      'To show you information from your 3P account that is relevant' +
      ' to the recipients of the email, this add-on needs authorization' +
      ' to: <ul><li>Read recipients of the email</li>' +
      '         <li>Read contact information from 3P account</li></ul>.';

  var card = CardService.newCardBuilder()
      .setHeader(CardService.newCardHeader()
          .setTitle('Authorization Required'))
      .addSection(CardService.newCardSection()
          .setHeader('This add-on needs access to your 3P account.')
          .addWidget(CardService.newTextParagraph()
              .setText(promptText))
          .addWidget(CardService.newButtonSet()
              .addButton(authButton)))
      .build();
  return [card];
}

/**
 * When connecting to the non-Google service, pass the name of the
 * custom UI callback function to the AuthorizationException object
 */
function accessProtectedResource(url, method_opt, headers_opt) {
  var service = getOAuthService();
  if (service.hasAccess()) {
    // Make the UrlFetch request and return the result.
    // ...
  } else {
    // Invoke the authorization flow using a custom authorization
    // prompt card.
    CardService.newAuthorizationException()
        .setAuthorizationUrl(service.getAuthorizationUrl())
        .setResourceDisplayName("Display name to show to the user")
        .setCustomUiCallback('create3PAuthorizationUi')
        .throwException();
  }
}

Google Workspace অ্যাপ জুড়ে থার্ড-পার্টি লগইন পরিচালনা করা

Google Workspace অ্যাড-অনগুলির জন্য একটি সাধারণ অ্যাপ্লিকেশন হল একটি Google Workspace হোস্ট অ্যাপ্লিকেশনের মধ্যে থেকে একটি থার্ড-পার্টি সিস্টেমের সাথে ইন্টারফেস দেওয়ার জন্য একটি ইন্টারফেস প্রদান করা। অ্যাপস স্ক্রিপ্টের জন্য OAuth2 লাইব্রেরি আপনাকে তৃতীয় পক্ষের পরিষেবাগুলির সাথে সংযোগ তৈরি এবং পরিচালনা করতে সাহায্য করতে পারে৷

থার্ড-পার্টি সিস্টেমের জন্য প্রায়শই ব্যবহারকারীর আইডি, পাসওয়ার্ড বা অন্যান্য শংসাপত্র ব্যবহার করে সাইন ইন করতে হয়। কোনও ব্যবহারকারী যখন একটি Google Workspace হোস্ট ব্যবহার করার সময় আপনার থার্ড-পার্টি পরিষেবাতে সাইন-ইন করেন, তখন আপনাকে অবশ্যই নিশ্চিত করতে হবে যে তারা অন্য Google Workspace হোস্টে স্যুইচ করলে তাকে আবার সাইন-ইন করতে হবে না। বারবার লগইন অনুরোধ প্রতিরোধ করতে, ব্যবহারকারীর বৈশিষ্ট্য বা আইডি টোকেন ব্যবহার করুন। এগুলি নিম্নলিখিত বিভাগে ব্যাখ্যা করা হয়েছে।

ব্যবহারকারীর বৈশিষ্ট্য

আপনি Apps Script এর ব্যবহারকারী বৈশিষ্ট্যে ব্যবহারকারীর সাইন-ইন ডেটা সংরক্ষণ করতে পারেন। উদাহরণস্বরূপ, আপনি তাদের লগইন পরিষেবা থেকে আপনার নিজস্ব JWT তৈরি করতে পারেন এবং এটি একটি ব্যবহারকারীর সম্পত্তিতে রেকর্ড করতে পারেন, বা তাদের পরিষেবার জন্য ব্যবহারকারীর নাম এবং পাসওয়ার্ড রেকর্ড করতে পারেন।

ব্যবহারকারীর বৈশিষ্ট্যগুলি এমনভাবে স্কোপ করা হয়েছে যে সেগুলি শুধুমাত্র আপনার অ্যাড-অনের স্ক্রিপ্টের মধ্যে সেই ব্যবহারকারী দ্বারা অ্যাক্সেসযোগ্য। অন্যান্য ব্যবহারকারী এবং অন্যান্য স্ক্রিপ্ট এই বৈশিষ্ট্যগুলি অ্যাক্সেস করতে পারে না। আরো বিস্তারিত জানার জন্য PropertiesService দেখুন।

আইডি টোকেন

আপনি আপনার পরিষেবার জন্য লগইন শংসাপত্র হিসাবে একটি Google ID টোকেন ব্যবহার করতে পারেন৷ এটি একক সাইন-অন অর্জনের একটি উপায়। ব্যবহারকারীরা ইতিমধ্যেই গুগলে লগ ইন করেছেন কারণ তারা একটি Google হোস্ট অ্যাপে রয়েছে৷