আপনার Google Workspace অ্যাড-অনকে একটি থার্ড-পার্টি পরিষেবাতে কানেক্ট করুন, আপনার Google Workspace অ্যাড-অনকে কোনও থার্ড-পার্টি পরিষেবার সাথে কানেক্ট করুন, আপনার Google Workspace অ্যাড-অনকে কোনও থার্ড-পার্টি পরিষেবার সাথে কানেক্ট করুন, আপনার Google Workspace অ্যাড-অনকে এতে কানেক্ট করুন একটি তৃতীয় পক্ষের পরিষেবা

লিঙ্ক প্রিভিউ থেকে তৈরি একটি কাস্টম অনুমোদন কার্ড, যাতে কোম্পানির লোগো, একটি বিবরণ এবং একটি সাইন-ইন বাটন অন্তর্ভুক্ত রয়েছে।
একটি অ্যাড-অনের জন্য সাইন-ইন কার্ড ইন্টারফেস, যা তৃতীয় পক্ষের পরিষেবা থেকে লিঙ্কগুলির প্রিভিউ দেখায়।

আপনার গুগল ওয়ার্কস্পেস অ্যাড-অন যদি এমন কোনো তৃতীয় পক্ষের পরিষেবা বা এপিআই-এর সাথে সংযোগ স্থাপন করে যার জন্য অনুমোদনের প্রয়োজন হয়, তাহলে অ্যাড-অনটি ব্যবহারকারীদের সাইন ইন করতে এবং অ্যাক্সেস অনুমোদন করতে অনুরোধ করতে পারে।

এই পৃষ্ঠায় একটি অনুমোদন প্রবাহ (যেমন OAuth) ব্যবহার করে ব্যবহারকারীদের প্রমাণীকরণের পদ্ধতি ব্যাখ্যা করা হয়েছে, যার মধ্যে নিম্নলিখিত ধাপগুলো অন্তর্ভুক্ত রয়েছে:

  1. কখন অনুমোদনের প্রয়োজন তা শনাক্ত করুন।
  2. একটি কার্ড ইন্টারফেস ফিরিয়ে আনুন যা ব্যবহারকারীদের পরিষেবাটিতে সাইন ইন করতে অনুরোধ করে।
  3. অ্যাড-অনটি রিফ্রেশ করুন যাতে ব্যবহারকারীরা পরিষেবা বা সুরক্ষিত রিসোর্সটি অ্যাক্সেস করতে পারেন।

যদি আপনার অ্যাড-অনের জন্য শুধুমাত্র ব্যবহারকারীর পরিচয়ের প্রয়োজন হয়, তাহলে আপনি সরাসরি ব্যবহারকারীদের Google Workspace ID বা ইমেল ঠিকানা ব্যবহার করে প্রমাণীকরণ করতে পারেন। প্রমাণীকরণের জন্য ইমেল ঠিকানা ব্যবহার করতে, JSON অনুরোধ যাচাইকরণ দেখুন। যদি আপনি Google Apps Script ব্যবহার করে আপনার অ্যাড-অন তৈরি করে থাকেন, তাহলে আপনি OAuth2 for Google Apps Script লাইব্রেরি ব্যবহার করে এই প্রক্রিয়াটিকে আরও সহজ করতে পারেন (এর একটি OAuth1 সংস্করণও রয়েছে)।

অনুমোদনের প্রয়োজন আছে তা শনাক্ত করুন।

আপনার অ্যাড-অন ব্যবহার করার সময়, ব্যবহারকারীরা বিভিন্ন কারণে কোনো সুরক্ষিত রিসোর্স অ্যাক্সেস করার জন্য অনুমোদিত নাও হতে পারেন, যেমন:

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

আপনার অ্যাড-অনটির এই ক্ষেত্রগুলো শনাক্ত করা উচিত, যাতে ব্যবহারকারীরা সাইন ইন করে আপনার পরিষেবাটি ব্যবহার করতে পারেন।

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

ব্যবহারকারীদের আপনার পরিষেবাতে সাইন ইন করতে বলুন।

যখন আপনার অ্যাড-অনটি শনাক্ত করে যে অনুমোদনের প্রয়োজন, তখন ব্যবহারকারীদের পরিষেবাটিতে সাইন ইন করার জন্য অনুরোধ জানাতে অ্যাড-অনটিকে অবশ্যই একটি কার্ড ইন্টারফেস ফেরত দিতে হবে। সাইন-ইন কার্ডটি অবশ্যই ব্যবহারকারীদের আপনার পরিকাঠামোতে তৃতীয় পক্ষের প্রমাণীকরণ এবং অনুমোদন প্রক্রিয়াটি সম্পন্ন করার জন্য পুনঃনির্দেশিত করবে।

HTTP এন্ডপয়েন্ট ব্যবহার করে আপনার অ্যাড-অন তৈরি করার সময়, আমরা সুপারিশ করি যে আপনি Google Sign-in দিয়ে ডেস্টিনেশন অ্যাপটিকে সুরক্ষিত করুন এবং সাইন-ইন করার সময় ইস্যু করা আইডেন্টিটি টোকেন ব্যবহার করে ইউজার আইডি সংগ্রহ করুন। সাব-ক্লেমটিতে ব্যবহারকারীর অনন্য আইডি থাকে এবং এটিকে আপনার অ্যাড-অনের আইডির সাথে মেলানো যেতে পারে।

একটি সাইন-ইন কার্ড তৈরি করুন এবং ফেরত দিন

আপনার পরিষেবার সাইন-ইন কার্ডের জন্য, আপনি গুগলের বেসিক অথরাইজেশন কার্ড ব্যবহার করতে পারেন, অথবা আপনার প্রতিষ্ঠানের লোগোর মতো অতিরিক্ত তথ্য প্রদর্শনের জন্য একটি কার্ড কাস্টমাইজ করতে পারেন। আপনি যদি আপনার অ্যাড-অনটি সর্বজনীনভাবে প্রকাশ করেন, তবে আপনাকে অবশ্যই একটি কাস্টম কার্ড ব্যবহার করতে হবে।

মৌলিক অনুমোদন কার্ড

নিচের ছবিতে গুগলের বেসিক অথরাইজেশন কার্ডের একটি উদাহরণ দেখানো হয়েছে:

উদাহরণ অ্যাকাউন্টের জন্য প্রাথমিক অনুমোদনের অনুরোধ।
এক্সাম্পল অ্যাকাউন্টের জন্য প্রাথমিক অনুমোদনের অনুরোধ। অনুরোধে বলা হচ্ছে যে, অ্যাড-অনটি অতিরিক্ত তথ্য দেখাতে চায়, কিন্তু অ্যাকাউন্টটি অ্যাক্সেস করার জন্য ব্যবহারকারীর অনুমোদনের প্রয়োজন।

ব্যবহারকারীদের কাছে প্রাথমিক অনুমোদন কার্ড চাইতে হলে, আপনাকে অবশ্যই AuthorizationError অবজেক্টটি রিটার্ন করতে হবে। নিচের কোডটিতে একটি AuthorizationError অবজেক্টের উদাহরণ দেখানো হয়েছে:

অ্যাপস স্ক্রিপ্ট

CardService.newAuthorizationException()
    .setAuthorizationUrl('AUTHORIZATION_URL')
    .setResourceDisplayName('RESOURCE_DISPLAY_NAME')
    .throwException();

JSON

নিম্নলিখিত JSON প্রতিক্রিয়া ফেরত দিন:

{
  "basic_authorization_prompt": {
    "authorization_url": "AUTHORIZATION_URL",
    "resource": "RESOURCE_DISPLAY_NAME"
  }
}

নিম্নলিখিতগুলি প্রতিস্থাপন করুন:

  • AUTHORIZATION_URL : যে ওয়েব অ্যাপটি অনুমোদন পরিচালনা করে, তার ইউআরএল।
  • RESOURCE_DISPLAY_NAME : সুরক্ষিত রিসোর্স বা পরিষেবার প্রদর্শিত নাম। এই নামটি ব্যবহারকারীকে অনুমোদনের অনুরোধে দেখানো হয়। উদাহরণস্বরূপ, যদি আপনার RESOURCE_DISPLAY_NAME হয় Example Account , তাহলে অনুরোধে লেখা থাকবে "এই অ্যাড-অনটি অতিরিক্ত তথ্য দেখাতে চায়, কিন্তু আপনার ‘এক্সাম্পল অ্যাকাউন্ট’ অ্যাক্সেস করার জন্য অনুমোদনের প্রয়োজন।"

অনুমোদন সম্পন্ন করার পর, সুরক্ষিত রিসোর্সটি অ্যাক্সেস করার জন্য ব্যবহারকারীকে অ্যাড-অনটি রিফ্রেশ করতে বলা হয়।

গুগল চ্যাটে অনুমোদন কার্ড ফেরত দিন

যদি আপনার অ্যাড-অনটি গুগল চ্যাটকে সম্প্রসারিত করে এবং ব্যবহারকারী গুগল চ্যাটের মধ্যেই এটি চালান, তবে তিনি ম্যানুয়াল রিফ্রেশ ছাড়াই অনুমোদন প্রক্রিয়াটি সম্পন্ন করতে পারবেন। ট্রিগারটি 'Message' , 'Added to space' , বা 'App command' হলে গুগল চ্যাট পূর্ববর্তী এক্সিকিউশনের স্বয়ংক্রিয়ভাবে পুনরায় চেষ্টা করা সমর্থন করে। এই ট্রিগারগুলির জন্য, আপনার অ্যাড-অনটি ইভেন্ট পেলোডে completeRedirectUri গ্রহণ করে। স্বয়ংক্রিয়ভাবে পুনরায় চেষ্টা চালু করার জন্য আপনাকে অবশ্যই আপনার কনফিগারেশন URL-এ completeRedirectUri এনকোড করতে হবে। এই URL-এ রিডাইরেক্ট করা হলে গুগল চ্যাট বুঝতে পারে যে কনফিগারেশন অনুরোধটি পূরণ হয়েছে, এবং এটি গুগল চ্যাটকে পূর্ববর্তী এক্সিকিউশনটি পুনরায় চেষ্টা করার সুযোগ দেয়।

যখন কোনো ব্যবহারকারীকে মূল বার্তায় দেওয়া configCompleteRedirectUrl এ সফলভাবে পুনঃনির্দেশিত করা হয়, তখন গুগল চ্যাট নিম্নলিখিত ধাপগুলো সম্পাদন করে:

  1. সূচনাকারী ব্যবহারকারীর কাছে প্রদর্শিত প্রম্পটটি মুছে দেয়।
  2. মূল ইভেন্ট অবজেক্টটি একই অ্যাড-অনে দ্বিতীয়বার পাঠায়।

আপনি যদি কনফিগারেশন URL-এ completeRedirectUri এনকোড না করেন, তাহলেও ব্যবহারকারী অনুমোদন প্রক্রিয়াটি সম্পন্ন করতে পারবেন। তবে, Google Chat পূর্ববর্তী প্রক্রিয়াটি পুনরায় চেষ্টা করে না এবং ব্যবহারকারীকে ম্যানুয়ালি আপনার অ্যাড-অনটি আবার চালু করতে হবে।

নিম্নলিখিত কোড নমুনাটি দেখায় কিভাবে একটি চ্যাট অ্যাপ অফলাইন OAuth2 ক্রেডেনশিয়াল অনুরোধ করতে পারে, সেগুলিকে একটি ডেটাবেসে সংরক্ষণ করতে পারে এবং ব্যবহারকারীর প্রমাণীকরণের মাধ্যমে API কল করার জন্য সেগুলি ব্যবহার করতে পারে।

অ্যাপস স্ক্রিপ্ট

নোড.জেএস

পাইথন

জাভা

কাস্টম অনুমোদন কার্ড

অনুমোদন প্রম্পটটি পরিবর্তন করতে, আপনি আপনার পরিষেবার সাইন-ইন অভিজ্ঞতার জন্য একটি কাস্টম কার্ড তৈরি করতে পারেন।

আপনি যদি আপনার অ্যাড-অনটি সর্বজনীনভাবে প্রকাশ করেন, তাহলে চ্যাট ব্যতীত অন্য সকল গুগল ওয়ার্কস্পেস হোস্ট অ্যাপ্লিকেশনের জন্য আপনাকে অবশ্যই একটি কাস্টম অনুমোদন কার্ড ব্যবহার করতে হবে। গুগল ওয়ার্কস্পেস মার্কেটপ্লেসে প্রকাশের প্রয়োজনীয়তা সম্পর্কে আরও জানতে, ‘অ্যাপ পর্যালোচনা সম্পর্কে’ দেখুন।

ফেরত দেওয়া কার্ডটিতে নিম্নলিখিত বিষয়গুলো অবশ্যই থাকতে হবে:

  • ব্যবহারকারীকে স্পষ্টভাবে জানিয়ে দিন যে অ্যাড-অনটি তার পক্ষ থেকে একটি নন-গুগল পরিষেবা অ্যাক্সেস করার অনুমতি চাইছে।
  • অনুমোদন পেলে অ্যাড-অনটি কী করতে সক্ষম, তা স্পষ্ট করে দিন।
  • একটি বাটন বা অনুরূপ উইজেট রাখুন যা ব্যবহারকারীকে সার্ভিসটির অথরাইজেশন ইউআরএল-এ নিয়ে যাবে। নিশ্চিত করুন যে এই উইজেটটির কার্যকারিতা ব্যবহারকারীর কাছে সুস্পষ্ট।
  • পূর্ববর্তী উইজেটটিকে অবশ্যই তার OpenLink অবজেক্টে OnClose.RELOAD সেটিংটি ব্যবহার করতে হবে, যাতে অনুমোদন পাওয়ার পর অ্যাড-অনটি রিলোড হয়।
  • অনুমোদন প্রম্পট থেকে খোলা সমস্ত লিঙ্কে অবশ্যই HTTPS ব্যবহার করতে হবে।

নিচের ছবিতে একটি অ্যাড-অনের হোমপেজের জন্য তৈরি একটি কাস্টম অথরাইজেশন কার্ডের নমুনা দেখানো হয়েছে। কার্ডটিতে একটি লোগো, বিবরণ এবং সাইন-ইন বাটন রয়েছে:

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

নিম্নলিখিত কোডটি দেখায় কিভাবে এই কাস্টম কার্ড উদাহরণটি ব্যবহার করতে হয়:

অ্যাপস স্ক্রিপ্ট

function customAuthorizationCard() {
    let cardSection1Image1 = CardService.newImage()
        .setImageUrl('LOGO_URL')
        .setAltText('LOGO_ALT_TEXT');

    let cardSection1Divider1 = CardService.newDivider();

    let cardSection1TextParagraph1 = CardService.newTextParagraph()
        .setText('DESCRIPTION');

    let cardSection1ButtonList1Button1 = CardService.newTextButton()
        .setText('Sign in')
        .setBackgroundColor('#0055ff')
        .setTextButtonStyle(CardService.TextButtonStyle.FILLED)
        .setAuthorizationAction(CardService.newAuthorizationAction()
            .setAuthorizationUrl('AUTHORIZATION_URL'));

    let cardSection1ButtonList1 = CardService.newButtonSet()
        .addButton(cardSection1ButtonList1Button1);

    let cardSection1TextParagraph2 = CardService.newTextParagraph()
        .setText('TEXT_SIGN_UP');

    let cardSection1 = CardService.newCardSection()
        .addWidget(cardSection1Image1)
        .addWidget(cardSection1Divider1)
        .addWidget(cardSection1TextParagraph1)
        .addWidget(cardSection1ButtonList1)
        .addWidget(cardSection1TextParagraph2);

    let card = CardService.newCardBuilder()
        .addSection(cardSection1)
        .build();
    return [card];
}

function startNonGoogleAuth() {
    CardService.newAuthorizationException()
        .setAuthorizationUrl('AUTHORIZATION_URL')
        .setResourceDisplayName('RESOURCE_DISPLAY_NAME')
        .setCustomUiCallback('customAuthorizationCard')
        .throwException();
  }

JSON

নিম্নলিখিত JSON প্রতিক্রিয়া ফেরত দিন:

{
  "custom_authorization_prompt": {
    "action": {
      "navigations": [
        {
          "pushCard": {
            "sections": [
              {
                "widgets": [
                  {
                    "image": {
                      "imageUrl": "LOGO_URL",
                      "altText": "LOGO_ALT_TEXT"
                    }
                  },
                  {
                    "divider": {}
                  },
                  {
                    "textParagraph": {
                      "text": "DESCRIPTION"
                    }
                  },
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Sign in",
                          "onClick": {
                            "openLink": {
                              "url": "AUTHORIZATION_URL",
                              "onClose": "RELOAD",
                              "openAs": "OVERLAY"
                            }
                          },
                          "color": {
                            "red": 0,
                            "green": 0,
                            "blue": 1,
                            "alpha": 1,
                          }
                        }
                      ]
                    }
                  },
                  {
                    "textParagraph": {
                      "text": "TEXT_SIGN_UP"
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

নিম্নলিখিতগুলি প্রতিস্থাপন করুন:

  • LOGO_URL : লোগো বা ছবির জন্য ইউআরএল। এটি অবশ্যই একটি পাবলিক ইউআরএল হতে হবে।
  • LOGO_ALT_TEXT : লোগো বা ছবির জন্য অল্টারনেটিভ টেক্সট, যেমন Cymbal Labs Logo
  • DESCRIPTION : ব্যবহারকারীদের সাইন ইন করার জন্য একটি আহ্বান, যেমন Sign in to get started '।
  • সাইন-ইন বাটনটি আপডেট করতে:
    • AUTHORIZATION_URL : যে ওয়েব অ্যাপটি অনুমোদন পরিচালনা করে, তার ইউআরএল।
    • ঐচ্ছিক: বাটনের রঙ পরিবর্তন করতে, color ফিল্ডের RGBA ফ্লোট ভ্যালুগুলো আপডেট করুন। অ্যাপস স্ক্রিপ্টের জন্য, হেক্সাডেসিমেল ভ্যালু ব্যবহার করে setBackgroundColor মেথডটি আপডেট করুন।
  • TEXT_SIGN_UP : এমন একটি লেখা যা ব্যবহারকারীদের একটি অ্যাকাউন্ট তৈরি করতে উৎসাহিত করে, যদি তাদের কোনো অ্যাকাউন্ট না থাকে। উদাহরণস্বরূপ, New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here

গুগল ওয়ার্কস্পেস অ্যাপ জুড়ে তৃতীয় পক্ষের লগইনগুলি পরিচালনা করুন

গুগল ওয়ার্কস্পেস অ্যাড-অনগুলির একটি সাধারণ প্রয়োগ হলো গুগল ওয়ার্কস্পেস হোস্ট অ্যাপ্লিকেশনের ভেতর থেকে কোনো তৃতীয় পক্ষের সিস্টেমের সাথে যোগাযোগের জন্য একটি ইন্টারফেস প্রদান করা।

তৃতীয় পক্ষের সিস্টেমগুলিতে প্রায়শই ব্যবহারকারীকে ইউজার আইডি, পাসওয়ার্ড বা অন্য কোনো ক্রেডেনশিয়াল ব্যবহার করে সাইন ইন করতে হয়। যখন কোনো ব্যবহারকারী একটি গুগল ওয়ার্কস্পেস হোস্ট ব্যবহার করার সময় আপনার তৃতীয় পক্ষের পরিষেবাতে সাইন ইন করেন, তখন আপনাকে অবশ্যই নিশ্চিত করতে হবে যে তিনি অন্য গুগল ওয়ার্কস্পেস হোস্টে স্থানান্তরিত হলে তাকে যেন পুনরায় সাইন ইন করতে না হয়।

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

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

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

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

আইডি টোকেন

আপনি আপনার পরিষেবার লগইন ক্রেডেনশিয়াল হিসেবে একটি গুগল আইডি টোকেন ব্যবহার করতে পারেন। এটি সিঙ্গেল সাইন-অন বাস্তবায়নের একটি উপায়। ব্যবহারকারীরা ইতিমধ্যেই গুগলে লগ ইন করা থাকেন, কারণ তাঁরা একটি গুগল হোস্ট অ্যাপে থাকেন।

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

নিম্নলিখিত অ্যাপস স্ক্রিপ্ট কোড নমুনাটি দেখায় কিভাবে OAuth প্রয়োজন এমন একটি নন-গুগল এপিআই ব্যবহার করার জন্য একটি অ্যাড-অন কনফিগার করতে হয়। এই নমুনাটি এপিআই অ্যাক্সেস করার জন্য একটি সার্ভিস তৈরি করতে OAuth2 for Apps Script লাইব্রেরিটি ব্যবহার করে।

অ্যাপস স্ক্রিপ্ট

/**
* 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.
*/
function authCallback(callbackRequest) {
  var authorized = getOAuthService().handleCallback(callbackRequest);
  if (authorized) {
    return HtmlService.createHtmlOutput(
      'Success!');
  } 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();
}