Google Workspace eklentinizi üçüncü taraf hizmetine bağlama

Şirketin logosunu, bir açıklamayı ve oturum açma düğmesini içeren bir bağlantı önizlemesinden alınan özel yetkilendirme kartı.
Üçüncü taraf hizmetlerinden gelen bağlantıları önizleyen bir eklenti için oturum açma kartı arayüzü.

Google Workspace eklentiniz, yetkilendirme gerektiren bir üçüncü taraf hizmetine veya API'ye bağlanıyorsa eklenti, kullanıcılardan oturum açıp erişimi yetkilendirmelerini isteyebilir.

Bu sayfada, yetkilendirme akışı (ör. OAuth) kullanarak kullanıcıların nasıl kimlik doğrulanacağı açıklanmaktadır. Bu işlem aşağıdaki adımları içerir:

  1. Yetkilendirme gerektiğinde bunu algılayın.
  2. Kullanıcılardan hizmette oturum açmalarını isteyen bir kart arayüzü döndürün.
  3. Kullanıcıların hizmete veya korunan kaynağa erişebilmesi için eklentiyi yenileyin.

Eklentiniz yalnızca kullanıcı kimliğini gerektiriyorsa kullanıcıları Google Workspace kimliklerini veya e-posta adreslerini kullanarak doğrudan doğrulayabilirsiniz. Kimlik doğrulama için e-posta adresini kullanmak üzere JSON isteklerini doğrulama başlıklı makaleyi inceleyin. Eklentinizi Google Apps Komut Dosyası'nı kullanarak oluşturduysanız Google Apps Komut Dosyası için OAuth2 kitaplığını kullanarak bu süreci kolaylaştırabilirsiniz (OAuth1 sürümü de mevcuttur).

Yetkilendirme gerektiğinin algılanması

Kullanıcılar, eklentinizi kullanırken çeşitli nedenlerle (ör. aşağıdakiler) korunan bir kaynağa erişmek için yetkilendirilmemiş olabilir:

  • Üçüncü taraf hizmete bağlanmak için henüz bir erişim jetonu oluşturulmamıştır veya jetonun süresi dolmuştur.
  • Erişim jetonu, istenen kaynağı kapsamıyor.
  • Erişim jetonu, isteğin gerekli kapsamlarını içermiyor.

Kullanıcıların oturum açıp hizmetinize erişebilmesi için eklentiniz bu durumları algılamalıdır.

Apps Komut Dosyası'nda geliştirme yapıyorsanız OAuth kitaplığı hasAccess() işlevi, bir hizmete erişiminiz olup olmadığını söyleyebilir. Alternatif olarak, UrlFetchApp fetch() isteklerini kullanırken muteHttpExceptions parametresini true olarak ayarlayabilirsiniz. Bu, isteğin başarısız olması durumunda istisna oluşturulmasını önler ve döndürülen HttpResponse nesnesindeki istek yanıt kodunu ve içeriğini incelemenize olanak tanır.

Kullanıcılardan hizmetinizde oturum açmalarını isteme

Eklentiniz yetkilendirme gerektiğini algıladığında, kullanıcılardan hizmette oturum açmalarını istemek için kart arayüzünü döndürmelidir. Oturum açma kartı, kullanıcıları altyapınızda üçüncü taraf kimlik doğrulama ve yetkilendirme sürecini tamamlamaya yönlendirmelidir.

Eklentinizi HTTP uç noktalarını kullanarak oluştururken hedef uygulamayı Google ile oturum açma ile korumanızı ve oturum açma sırasında verilen kimlik jetonunu kullanarak kullanıcı kimliğini almanızı öneririz. Alt talep, kullanıcının benzersiz kimliğini içerir ve eklentinizdeki kimlikle ilişkilendirilebilir.

Oturum açma kartı oluşturma ve döndürme

Hizmetinizin oturum açma kartı için Google'ın temel yetkilendirme kartını kullanabilir veya bir kartı özelleştirerek kuruluşunuzun logosu gibi ek bilgiler gösterebilirsiniz. Eklentinizi herkese açık olarak yayınlıyorsanız özel kart kullanmanız gerekir.

Temel yetkilendirme kartı

Aşağıdaki resimde, Google'ın temel yetkilendirme kartı örneği gösterilmektedir:

Örnek Hesap için temel yetkilendirme istemi. İstemde, eklentinin ek bilgiler göstermek istediği ancak hesaba erişmek için kullanıcının onayına ihtiyaç duyduğu belirtiliyor.

Kullanıcılara temel yetkilendirme kartı göstermek için nesneyi döndürmeniz gerekir AuthorizationError. Aşağıdaki kodda bir AuthorizationError nesnesi örneği gösterilmektedir:

Apps Komut Dosyası

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

JSON

Aşağıdaki JSON yanıtını döndürün:

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

Aşağıdakini değiştirin:

  • AUTHORIZATION_URL: Yetkilendirmeyi işleyen web uygulamasının URL'si.
  • RESOURCE_DISPLAY_NAME: Korunan kaynak veya hizmetin görünen adı. Bu ad, yetkilendirme isteminde kullanıcıya gösterilir. Örneğin, RESOURCE_DISPLAY_NAME adresiniz Example Account ise istemde "Bu eklenti ek bilgiler göstermek istiyor ancak Example Account hesabınıza erişmesi için onay gerekli." ifadesi yer alır.

Yetkilendirme tamamlandıktan sonra kullanıcıdan korunan kaynağa erişmek için eklentiyi yenilemesi istenir.

Google Chat'te iade yetkilendirme kartları

Eklentiniz Google Chat'i genişletiyorsa ve kullanıcı eklentiyi Google Chat'te çalıştırıyorsa kullanıcı, yetkilendirme işlemini manuel yenileme yapmadan tamamlayabilir. Google Chat, tetikleyici Mesaj, Alana eklendi veya Uygulama komutu ise önceki yürütmenin otomatik olarak yeniden denenmesini destekler. Bu tetikleyiciler için eklentiniz, etkinlik yükünde completeRedirectUri alır. Otomatik yeniden denemeyi tetiklemek için yapılandırma URL'nizde completeRedirectUri karakterini kodlamanız gerekir. Bu URL'ye yönlendirme, Google Chat'e yapılandırma isteğinin karşılandığını bildirir ve Google Chat'in önceki yürütmeyi yeniden denemesine olanak tanır.

Kullanıcı, orijinal mesajda sağlanan configCompleteRedirectUrl adresine başarıyla yönlendirildiğinde Google Chat aşağıdaki adımları uygular:

  1. İşlemi başlatan kullanıcıya gösterilen istemi siler.
  2. Orijinal etkinlik nesnesini aynı eklentiye ikinci kez gönderir.

Yapılandırma URL'sinde completeRedirectUri kodlamazsanız kullanıcı yetkilendirme akışını yine de tamamlayabilir. Ancak Google Chat, önceki yürütmeyi yeniden denemez ve kullanıcının eklentinizi manuel olarak tekrar çağırması gerekir.

Aşağıdaki kod örneğinde, bir Chat uygulamasının nasıl çevrimdışı OAuth2 kimlik bilgileri isteyebileceği, bunları bir veritabanında saklayabileceği ve kullanıcı kimlik doğrulaması ile API çağrıları yapmak için kullanabileceği gösterilmektedir.

Özel yetkilendirme kartı

Yetkilendirme istemini değiştirmek için hizmetinizin oturum açma deneyimiyle ilgili özel bir kart oluşturabilirsiniz.

Eklentinizi herkese açık olarak yayınlıyorsanız Chat hariç tüm Google Workspace ana makine uygulamaları için özel bir yetkilendirme kartı kullanmanız gerekir. Google Workspace Marketplace'te yayınlama koşulları hakkında daha fazla bilgi edinmek için Uygulama inceleme hakkında başlıklı makaleyi inceleyin.

Döndürülen kart aşağıdakileri yapmalıdır:

  • Eklentinin, kullanıcı adına Google dışı bir hizmete erişim izni istediğini kullanıcıya açıkça belirtin.
  • Yetkilendirilirse eklentinin neler yapabileceğini açıkça belirtin.
  • Kullanıcıyı hizmetin yetkilendirme URL'sine yönlendiren bir düğme veya benzer bir widget içermelidir. Bu widget'ın işlevinin kullanıcı tarafından kolayca anlaşılmasını sağlayın.
  • Yukarıdaki widget, yetkilendirme alındıktan sonra eklentinin yeniden yüklenmesini sağlamak için OpenLink nesnesinde OnClose.RELOAD ayarını kullanmalıdır.
  • Yetkilendirme isteminden açılan tüm bağlantılar HTTPS kullanmalıdır.

Aşağıdaki resimde, bir eklentinin ana sayfası için örnek bir özel yetkilendirme kartı gösterilmektedir. Kartta logo, açıklama ve oturum açma düğmesi bulunur:

Cymbal Labs için şirketin logosunu, bir açıklamayı ve oturum açma düğmesini içeren özel bir yetkilendirme kartı.

Aşağıdaki kodda bu özel kart örneğinin nasıl kullanılacağı gösterilmektedir:

Apps Komut Dosyası

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

Aşağıdaki JSON yanıtını döndürün:

{
  "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"
                    }
                  }
                ]
              }
            ]
          }
        }
      ]
    }
  }
}

Aşağıdakini değiştirin:

  • LOGO_URL: Logo veya resmin URL'si. Herkese açık bir URL olmalıdır.
  • LOGO_ALT_TEXT: Logo veya resim için alternatif metin (ör. Cymbal Labs Logo).
  • DESCRIPTION: Kullanıcıların oturum açmasını sağlayan bir harekete geçirici mesaj (ör. Sign in to get started).
  • Oturum açma düğmesini güncellemek için:
    • AUTHORIZATION_URL: Yetkilendirmeyi işleyen web uygulamasının URL'si.
    • İsteğe bağlı: Düğme rengini değiştirmek için color alanının RGBA kayan değerlerini güncelleyin. Apps Komut Dosyası için setBackgroundColor() yöntemini onaltılık değerleri kullanarak güncelleyin.
  • TEXT_SIGN_UP: Kullanıcıları hesapları yoksa hesap oluşturmaya yönlendiren bir metin. Örneğin, New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here.

Google Workspace uygulamalarında üçüncü taraf girişlerini yönetme

Google Workspace eklentilerinin yaygın olarak kullanıldığı bir alan, Google Workspace ana uygulamasından üçüncü taraf sistemiyle etkileşim kurmak için arayüz sağlamaktır.

Üçüncü taraf sistemleri genellikle kullanıcının kullanıcı kimliği, şifre veya başka bir kimlik bilgisi kullanarak oturum açmasını gerektirir. Bir kullanıcı, Google Workspace ana makinesini kullanırken üçüncü taraf hizmetinizde oturum açtığında başka bir Google Workspace ana makinesine geçtiğinde tekrar oturum açması gerekmediğinden emin olmanız gerekir.

Apps Komut Dosyası'nda geliştirme yapıyorsanız kullanıcı özellikleri veya kimlik jetonlarıyla tekrarlanan giriş isteklerini önleyebilirsiniz. Bunlar aşağıdaki bölümlerde açıklanmıştır.

Kullanıcı özellikleri

Kullanıcının oturum açma verilerini Apps Komut Dosyası'nın kullanıcı özelliklerinde depolayabilirsiniz. Örneğin, giriş hizmetlerinden kendi JSON Web Token'ınızı (JWT) oluşturabilir ve bunu bir kullanıcı özelliğine kaydedebilir veya hizmetlerinin kullanıcı adını ve şifresini kaydedebilirsiniz.

Kullanıcı özellikleri, yalnızca eklentinizin komut dosyasında söz konusu kullanıcı tarafından erişilebilecek şekilde kapsamlandırılır. Diğer kullanıcılar ve diğer komut dosyaları bu özelliklere erişemez. Daha fazla bilgi için PropertiesService sayfasına bakın.

Kimlik jetonları

Hizmetiniz için giriş kimliği olarak Google kimlik jetonu kullanabilirsiniz. Bu, tek oturum açma elde etmenin bir yoludur. Kullanıcılar bir Google ana uygulamasında oldukları için Google'da zaten oturum açmış durumdadır.

Google dışı OAuth yapılandırma örneği

Aşağıdaki Apps Komut Dosyası kod örneğinde, OAuth gerektiren Google dışı bir API'yi kullanmak için eklentinin nasıl yapılandırılacağı gösterilmektedir. Bu örnekte, API'ye erişmek için bir hizmet oluşturmak üzere Apps Komut Dosyası için OAuth2 kitaplığı kullanılır.

Apps Komut Dosyası

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