
Jeśli dodatek do Google Workspace łączy się z usługą lub interfejsem API innej firmy, które wymagają autoryzacji, może wyświetlać użytkownikom prośbę o zalogowanie się i przyznanie dostępu.
Na tej stronie znajdziesz informacje o tym, jak uwierzytelniać użytkowników za pomocą procesu autoryzacji (np. OAuth), który obejmuje te czynności:
- wykrywać, kiedy wymagana jest autoryzacja;
- Zwróć interfejs karty, który wyświetla użytkownikom prośbę o zalogowanie się w usłudze.
- Odśwież dodatek, aby użytkownicy mogli uzyskać dostęp do usługi lub chronionego zasobu.
Jeśli dodatek wymaga tylko tożsamości użytkownika, możesz bezpośrednio uwierzytelniać użytkowników za pomocą ich identyfikatora Google Workspace lub adresu e-mail. Aby użyć adresu e-mail do uwierzytelniania, zapoznaj się z informacjami o sprawdzaniu poprawności żądań JSON. Jeśli dodatek został utworzony za pomocą Google Apps Script, możesz ułatwić sobie ten proces, korzystając z biblioteki OAuth2 dla Google Apps Script (dostępna jest też wersja OAuth1).
wykrywać, że wymagana jest autoryzacja;
Podczas korzystania z dodatku użytkownicy mogą nie mieć uprawnień dostępu do chronionego zasobu z różnych powodów, np.:
- Token dostępu do połączenia z usługą innej firmy nie został jeszcze wygenerowany lub wygasł.
- Token dostępu nie obejmuje żądanego zasobu.
- Token dostępu nie obejmuje zakresów wymaganych przez żądanie.
Dodatek powinien wykrywać takie przypadki, aby użytkownicy mogli się zalogować i uzyskać dostęp do usługi.
Jeśli tworzysz skrypty w Apps Script, funkcja biblioteki OAuth hasAccess()
może sprawdzić, czy masz dostęp do usługi.
Możesz też w przypadku żądań UrlFetchApp fetch()
ustawić parametr muteHttpExceptions
na true
. Zapobiega to zgłaszaniu wyjątku w przypadku niepowodzenia żądania i umożliwia sprawdzenie kodu odpowiedzi oraz treści w zwróconym obiekcie HttpResponse
.
Zachęcanie użytkowników do logowania się w usłudze
Gdy dodatek wykryje, że wymagana jest autoryzacja, musi zwrócić interfejs karty, aby poprosić użytkowników o zalogowanie się w usłudze. Karta logowania musi przekierowywać użytkowników, aby dokończyli proces uwierzytelniania i autoryzacji w infrastrukturze zewnętrznej.
Podczas tworzenia dodatku za pomocą punktów końcowych HTTP zalecamy zabezpieczenie aplikacji docelowej za pomocą logowania przez Google i uzyskanie identyfikatora użytkownika za pomocą tokena tożsamości wydanego podczas logowania. Roszczenie podrzędne zawiera unikalny identyfikator użytkownika i może być powiązane z identyfikatorem z Twojego dodatku.
Tworzenie i zwracanie karty logowania
W przypadku karty logowania do usługi możesz użyć podstawowej karty autoryzacji Google lub dostosować kartę, aby wyświetlać dodatkowe informacje, takie jak logo organizacji. Jeśli publikujesz dodatek publicznie, musisz użyć karty niestandardowej.
Podstawowa karta autoryzacji
Na ilustracji poniżej widać przykład podstawowej karty autoryzacji Google:

Aby wyświetlić użytkownikom podstawową kartę autoryzacji, musisz zwrócić obiekt
AuthorizationError
. Poniższy kod przedstawia przykład obiektu AuthorizationError
:
Google Apps Script
CardService.newAuthorizationException() .setAuthorizationUrl('AUTHORIZATION_URL') .setResourceDisplayName('RESOURCE_DISPLAY_NAME') .throwException();
JSON
Zwróć następującą odpowiedź JSON:
{
"basic_authorization_prompt": {
"authorization_url": "AUTHORIZATION_URL",
"resource": "RESOURCE_DISPLAY_NAME"
}
}
Zastąp następujące elementy:
AUTHORIZATION_URL
: adres URL aplikacji internetowej, która obsługuje autoryzację.RESOURCE_DISPLAY_NAME
: Wyświetlana nazwa chronionego zasobu lub usługi. Ta nazwa jest wyświetlana użytkownikowi w prompcie autoryzacji. Jeśli na przykład Twój adresRESOURCE_DISPLAY_NAME
toExample Account
, w prompcie pojawi się komunikat „Ten dodatek chciałby wyświetlić dodatkowe informacje, jednak w tym celu potrzebuje zgody na dostęp do Twojego konta Example Account”.
Po zakończeniu autoryzacji użytkownik zostanie poproszony o odświeżenie dodatku, aby uzyskać dostęp do chronionego zasobu.
Karty autoryzacji zwrotu w Google Chat
Jeśli dodatek rozszerza Google Chat i użytkownik uruchamia go w Google Chat, może dokończyć proces autoryzacji bez ręcznego odświeżania. Google Chat obsługuje automatyczne ponawianie poprzedniego wykonania, jeśli reguła to Wiadomość, Dodano do pokoju lub Polecenie aplikacji. W przypadku tych aktywatorów dodatek otrzymuje wartość completeRedirectUri
w ładunku zdarzenia.
Aby wywołać automatyczną ponowną próbę, musisz zakodować znak completeRedirectUri
w adresie URL konfiguracji. Przekierowanie na ten adres URL sygnalizuje Google Chat, że żądanie konfiguracji zostało spełnione, i umożliwia Google Chat ponowienie poprzedniego wykonania.
Gdy użytkownik zostanie przekierowany na adres configCompleteRedirectUrl
podany w oryginalnej wiadomości, Google Chat wykona te czynności:
- Usuwa prompt wyświetlany użytkownikowi, który zainicjował działanie.
- Wysyła pierwotny obiekt zdarzenia do tego samego dodatku po raz drugi.
Jeśli nie zakodujesz znaku completeRedirectUri
w adresie URL konfiguracji, użytkownik nadal będzie mógł przejść proces autoryzacji. Jednak Google Chat nie ponawia poprzedniego wykonania, a użytkownik musi ręcznie ponownie wywołać dodatek.
Poniższy przykładowy kod pokazuje, jak aplikacja do obsługi czatu może żądać danych logowania OAuth 2.0 w trybie offline, przechowywać je w bazie danych i używać ich do wywoływania interfejsów API z uwierzytelnianiem użytkownika.
Google Apps Script
Node.js
Python
Java
Niestandardowa karta autoryzacyjna
Aby zmodyfikować prośbę o autoryzację, możesz utworzyć kartę niestandardową na potrzeby logowania do usługi.
Jeśli publikujesz dodatek publicznie, musisz używać niestandardowej karty autoryzacji we wszystkich aplikacjach hosta Google Workspace z wyjątkiem Google Chat. Więcej informacji o wymaganiach dotyczących publikowania w Google Workspace Marketplace znajdziesz w artykule Informacje o sprawdzaniu aplikacji.
Zwrócona karta musi:
- Jasno poinformuj użytkownika, że dodatek prosi o uprawnienia dostępu do usługi innej niż Google w jego imieniu.
- Wyjaśnij, co dodatek może zrobić po uzyskaniu autoryzacji.
- zawierać przycisk lub podobny widżet, który przenosi użytkownika do adresu URL autoryzacji usługi; Upewnij się, że funkcja tego widżetu jest oczywista dla użytkownika.
- Powyższy widżet musi używać ustawienia
OnClose.RELOAD
w obiekcieOpenLink
, aby mieć pewność, że dodatek zostanie ponownie załadowany po otrzymaniu autoryzacji. - Wszystkie linki otwierane z poziomu prośby o autoryzację muszą używać protokołu HTTPS.
Obraz poniżej przedstawia przykładową kartę autoryzacji niestandardowej na stronie głównej dodatku. Karta zawiera logo, opis i przycisk logowania:

Poniższy kod pokazuje, jak używać tego przykładu karty niestandardowej:
Google Apps Script
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
Zwróć następującą odpowiedź 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"
}
}
]
}
]
}
}
]
}
}
}
Zastąp następujące elementy:
LOGO_URL
: adres URL logo lub obrazu. Musi to być publiczny adres URL.LOGO_ALT_TEXT
: tekst alternatywny logo lub obrazu, np.Cymbal Labs Logo
.DESCRIPTION
: wezwanie do działania, które zachęca użytkowników do zalogowania się, np.Sign in to get started
.- Aby zaktualizować przycisk logowania:
AUTHORIZATION_URL
: adres URL aplikacji internetowej, która obsługuje autoryzację.- Opcjonalnie: aby zmienić kolor przycisku, zaktualizuj wartości zmiennoprzecinkowe RGBA w polu
color
. W przypadku Apps Script zaktualizuj metodęsetBackgroundColor()
za pomocą wartości szesnastkowych.
TEXT_SIGN_UP
: tekst zachęcający użytkowników do utworzenia konta, jeśli go nie mają. Na przykład:New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here
.
Zarządzanie logowaniem za pomocą konta innej firmy w aplikacjach Google Workspace
Jednym z częstych zastosowań dodatków do Google Workspace jest udostępnianie interfejsu do interakcji z systemem innej firmy z poziomu aplikacji hosta Google Workspace.
Systemy innych firm często wymagają, aby użytkownik zalogował się za pomocą identyfikatora użytkownika, hasła lub innych danych logowania. Gdy użytkownik loguje się w usłudze innej firmy podczas korzystania z jednego hosta Google Workspace, musisz zadbać o to, aby nie musiał logować się ponownie po przełączeniu się na innego hosta Google Workspace.
Jeśli tworzysz skrypt w Apps Script, możesz zapobiec powtarzającym się prośbom o zalogowanie za pomocą właściwości użytkownika lub tokenów tożsamości. Zostały one opisane w kolejnych sekcjach.
Właściwości użytkownika
Dane logowania użytkownika możesz przechowywać we właściwościach użytkownika w Apps Script. Możesz na przykład utworzyć własny token sieciowy JSON (JWT) z usługi logowania użytkownika i zarejestrować go we właściwości użytkownika lub zarejestrować nazwę użytkownika i hasło do jego usługi.
Właściwości użytkownika są ograniczone do tego, że są dostępne tylko dla tego użytkownika w skrypcie dodatku. Inni użytkownicy i inne skrypty nie mają dostępu do tych właściwości. Więcej informacji znajdziesz w sekcji PropertiesService
.
Tokeny identyfikatora
Jako danych logowania do usługi możesz użyć tokena identyfikatora Google. Jest to sposób na wdrożenie logowania jednokrotnego. Użytkownicy są już zalogowani w Google, ponieważ korzystają z aplikacji hosta Google.
Przykład konfiguracji OAuth dla dostawcy innego niż Google
Poniższy przykładowy kod Apps Script pokazuje, jak skonfigurować dodatek do korzystania z interfejsu API innego niż Google, który wymaga OAuth. W tym przykładzie do utworzenia usługi umożliwiającej dostęp do interfejsu API używana jest biblioteka OAuth2 for Apps Script.
Google 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();
}