افزونه Google Workspace خود را به یک سرویس شخص ثالث متصل کنید

یک کارت مجوز سفارشی از پیش‌نمایش پیوند که شامل آرم شرکت، توضیحات و دکمه ورود است.
یک رابط کارت ورود به سیستم برای یک افزونه که پیوندهای یک سرویس شخص ثالث را پیش‌نمایش می‌کند.

اگر افزونه Google Workspace شما به یک سرویس یا API شخص ثالث که نیاز به مجوز دارد وصل می‌شود، این افزونه می‌تواند از کاربران بخواهد وارد سیستم شوند و اجازه دسترسی را بدهند.

این صفحه نحوه احراز هویت کاربران را با استفاده از یک جریان مجوز (مانند OAuth) توضیح می‌دهد که شامل مراحل زیر است:

  1. تشخیص زمانی که مجوز لازم است.
  2. رابط کارتی را برگردانید که از کاربران می خواهد وارد سرویس شوند.
  3. افزونه را بازخوانی کنید تا کاربران بتوانند به سرویس یا منبع محافظت شده دسترسی داشته باشند.

اگر افزونه شما فقط به هویت کاربر نیاز دارد، می‌توانید مستقیماً با استفاده از شناسه Google Workspace یا آدرس ایمیل کاربران را احراز هویت کنید. برای استفاده از آدرس ایمیل برای احراز هویت، به تأیید درخواست‌های JSON مراجعه کنید. اگر افزونه خود را با استفاده از Google Apps Script ساخته‌اید، می‌توانید با استفاده از کتابخانه OAuth2 برای Google Apps Script این فرآیند را آسان‌تر کنید ( نسخه OAuth1 نیز وجود دارد).

تشخیص دهید که مجوز لازم است

هنگام استفاده از افزونه شما، کاربران ممکن است به دلایل مختلفی از جمله موارد زیر مجاز به دسترسی به یک منبع محافظت شده نباشند:

  • رمز دسترسی برای اتصال به سرویس شخص ثالث هنوز ایجاد نشده یا منقضی شده است.
  • رمز دسترسی منبع درخواستی را پوشش نمی دهد.
  • رمز دسترسی محدوده های مورد نیاز درخواست را پوشش نمی دهد.

افزونه شما باید این موارد را شناسایی کند تا کاربران بتوانند وارد سیستم شوند و به سرویس شما دسترسی داشته باشند.

اگر در Apps Script می‌سازید، تابع OAuth library hasAccess() می‌تواند به شما بگوید که آیا به یک سرویس دسترسی دارید یا خیر. همچنین، هنگام استفاده از درخواست‌های UrlFetchApp fetch() ، می‌توانید پارامتر muteHttpExceptions را روی true تنظیم کنید. این امر از ایجاد یک استثنا در هنگام شکست درخواست جلوگیری می کند و به شما امکان می دهد کد پاسخ درخواست و محتوای موجود در شی HttpResponse برگشتی را بررسی کنید.

از کاربران بخواهید وارد سرویس شما شوند

وقتی برافزای شما تشخیص داد که مجوز لازم است، افزونه باید یک رابط کارتی را برگرداند تا از کاربران بخواهد وارد سرویس شوند. کارت ورود به سیستم باید کاربران را برای تکمیل فرآیند احراز هویت و مجوز شخص ثالث در زیرساخت شما هدایت کند.

هنگام ساختن برافزای خود با استفاده از نقاط پایانی HTTP، توصیه می‌کنیم از برنامه مقصد با Google Sign-in محافظت کنید و با استفاده از کد شناسایی صادر شده در حین ورود، شناسه کاربری را دریافت کنید. ادعای فرعی حاوی شناسه منحصر به فرد کاربر است و می تواند با شناسه افزونه شما مرتبط باشد.

یک کارت ورود به سیستم بسازید و برگردانید

برای کارت ورود به سیستم سرویس خود، می‌توانید از کارت مجوز اصلی Google استفاده کنید، یا می‌توانید کارتی را برای نمایش اطلاعات اضافی، مانند نشان‌واره سازمانتان، سفارشی کنید . اگر افزونه خود را به صورت عمومی منتشر می کنید، باید از کارت سفارشی استفاده کنید.

کارت مجوز پایه

تصویر زیر نمونه ای از کارت مجوز اولیه گوگل را نشان می دهد:

درخواست مجوز اولیه برای Example Account. درخواست می گوید که افزونه می خواهد اطلاعات بیشتری را نشان دهد، اما برای دسترسی به حساب به تایید کاربر نیاز دارد.

کد زیر نمونه ای از استفاده از کارت مجوز اولیه گوگل را نشان می دهد:

اسکریپت برنامه ها

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 باشد، در فرمان می‌گوید "این افزونه می‌خواهد اطلاعات بیشتری را نشان دهد، اما برای دسترسی به حساب مثال شما به تایید نیاز دارد."

پس از تکمیل مجوز، از کاربر خواسته می‌شود تا افزونه را برای دسترسی به منبع محافظت شده به‌روزرسانی کند.

کارت مجوز سفارشی

برای اصلاح درخواست مجوز، می توانید یک کارت سفارشی برای تجربه ورود به سیستم سرویس خود ایجاد کنید.

اگر افزونه خود را به صورت عمومی منتشر می کنید، باید از کارت مجوز سفارشی استفاده کنید. برای کسب اطلاعات بیشتر در مورد الزامات انتشار برای Google Workspace Marketplace، به بررسی درباره برنامه مراجعه کنید.

کارت برگشتی باید موارد زیر را انجام دهد:

  • برای کاربر روشن کنید که این افزونه از طرف او برای دسترسی به یک سرویس غیر Google اجازه می‌خواهد.
  • مشخص کنید که افزونه در صورت مجوز چه کاری می تواند انجام دهد.
  • حاوی یک دکمه یا ویجت مشابه است که کاربر را به URL مجوز سرویس می برد. مطمئن شوید که عملکرد این ویجت برای کاربر واضح است.
  • ویجت فوق باید از تنظیم OnClose.RELOAD در شی OpenLink خود استفاده کند تا اطمینان حاصل شود که افزونه پس از دریافت مجوز مجدداً بارگیری می شود.
  • همه پیوندهای باز شده از درخواست مجوز باید از HTTPS استفاده کنند .

تصویر زیر نمونه ای از کارت مجوز سفارشی برای صفحه اصلی یک افزونه را نشان می دهد. کارت شامل لوگو، توضیحات و دکمه ورود به سیستم است:

یک کارت مجوز سفارشی برای Cymbal Labs که شامل لوگوی شرکت، توضیحات و دکمه ورود است.

کد زیر نحوه استفاده از این نمونه کارت سفارشی را نشان می دهد:

اسکریپت برنامه ها

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 : نشانی اینترنتی یک لوگو یا تصویر. باید یک URL عمومی باشد.
  • LOGO_ALT_TEXT : متن جایگزین برای لوگو یا تصویر، مانند Cymbal Labs Logo .
  • DESCRIPTION : یک فراخوان برای اقدام برای ورود کاربران، مانند Sign in to get started .
  • برای به روز رسانی دکمه ورود به سیستم:
    • AUTHORIZATION_URL : نشانی اینترنتی برنامه وب که مجوز را مدیریت می کند.
    • اختیاری: برای تغییر رنگ دکمه، مقادیر شناور RGBA فیلد color را به‌روزرسانی کنید. برای Apps Script، متد setBackgroundColor() را با استفاده از مقادیر هگزادسیمال به‌روزرسانی کنید.
  • TEXT_SIGN_UP : متنی که از کاربران می خواهد در صورت نداشتن یک حساب کاربری ایجاد کنند. به عنوان مثال، New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here .

ورودهای شخص ثالث را در برنامه‌های Google Workspace مدیریت کنید

یکی از برنامه های رایج برای افزونه های Google Workspace، ارائه یک رابط برای تعامل با یک سیستم شخص ثالث از داخل یک برنامه میزبان Google Workspace است.

سیستم های شخص ثالث اغلب نیاز دارند که کاربر با استفاده از شناسه کاربری، رمز عبور یا سایر اطلاعات کاربری وارد سیستم شود. وقتی کاربر در حالی که از یک میزبان Google Workspace استفاده می‌کند به سیستم شخص ثالث شما وارد می‌شود، باید مطمئن شوید که وقتی به میزبان Google Workspace دیگری می‌رود، دوباره وارد سیستم نمی‌شود.

اگر در Apps Script ایجاد می‌کنید، می‌توانید از درخواست‌های مکرر ورود به سیستم با ویژگی‌های کاربر یا نشانه‌های ID جلوگیری کنید. این موارد در بخش های بعدی توضیح داده شده است.

ویژگی های کاربر

می‌توانید داده‌های ورود به سیستم کاربر را در ویژگی‌های کاربر Apps Script ذخیره کنید. برای مثال، می‌توانید JSON Web Token (JWT) خود را از سرویس ورود آنها ایجاد کنید و آن را در یک ویژگی کاربر ثبت کنید، یا نام کاربری و رمز عبور سرویس آنها را ثبت کنید.

دامنه ویژگی های کاربر به گونه ای است که فقط توسط آن کاربر در اسکریپت افزونه شما قابل دسترسی است. سایر کاربران و سایر اسکریپت ها نمی توانند به این ویژگی ها دسترسی داشته باشند. برای جزئیات بیشتر به PropertiesService مراجعه کنید.

نشانه های شناسه

می‌توانید از یک رمز Google ID به عنوان اعتبار ورود به سرویس خود استفاده کنید. این راهی برای دستیابی به یک ورود به سیستم است. کاربران قبلاً وارد Google شده اند زیرا در یک برنامه میزبان Google هستند.

نمونه پیکربندی OAuth غیر Google

نمونه کد Apps Script زیر نحوه پیکربندی یک افزونه را برای استفاده از API غیر Google که به OAuth نیاز دارد، نشان می‌دهد. این نمونه از کتابخانه OAuth2 for Apps Script برای ساخت سرویسی برای دسترسی به API استفاده می کند.

اسکریپت برنامه ها

/**
* 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();
}