
Se o complemento do Google Workspace se conectar a um serviço ou API de terceiros que exija autorização, ele poderá pedir que os usuários façam login e autorizem o acesso.
Nesta página, explicamos como autenticar usuários usando um fluxo de autorização (como o OAuth), que inclui as seguintes etapas:
- Detectar quando a autorização é necessária.
- Retorna uma interface de card que pede aos usuários para fazer login no serviço.
- Atualize o complemento para que os usuários possam acessar o serviço ou recurso protegido.
Se o complemento exigir apenas a identidade do usuário, você poderá autenticar usuários diretamente usando o ID ou o endereço de e-mail do Google Workspace. Para usar o endereço de e-mail na autenticação, consulte validação de solicitações JSON. Se você criou seu complemento usando o Google Apps Script, pode facilitar esse processo usando a biblioteca OAuth2 para Google Apps Script (também há uma versão do OAuth1).
Detectar que a autorização é necessária
Ao usar seu complemento, os usuários podem não ter autorização para acessar um recurso protegido por vários motivos, como os seguintes:
- Um token de acesso para se conectar ao serviço de terceiros ainda não foi gerado ou expirou.
- O token de acesso não abrange o recurso solicitado.
- O token de acesso não abrange os escopos necessários da solicitação.
O complemento precisa detectar esses casos para que os usuários possam fazer login e acessar seu serviço.
Se você estiver criando no Apps Script, a função
hasAccess()
da biblioteca OAuth pode informar se você tem acesso a um serviço.
Como alternativa, ao usar solicitações
UrlFetchApp fetch()
, defina o parâmetro muteHttpExceptions
como true
. Isso
evita que a solicitação gere uma exceção em caso de falha e permite
examinar o código e o conteúdo da resposta no objeto
HttpResponse
retornado.
Pedir que os usuários façam login no seu serviço
Quando o complemento detecta que a autorização é necessária, ele precisa retornar uma interface de card para pedir que os usuários façam login no serviço. O card de login precisa redirecionar os usuários para concluir o processo de autenticação e autorização de terceiros na sua infraestrutura.
Ao criar seu complemento usando endpoints HTTP, recomendamos que você proteja o app de destino com o Login do Google e receba o ID do usuário usando o token de identidade emitido durante o login. A declaração "sub" contém o ID exclusivo do usuário e pode ser correlacionada com o ID do seu complemento.
Criar e retornar um card de login
Para o card de login do seu serviço, você pode usar o card de autorização básica do Google ou personalizar um card para mostrar mais informações, como o logotipo da sua organização. Se você estiver publicando seu complemento publicamente, use um card personalizado.
Card de autorização básica
A imagem a seguir mostra um exemplo do cartão de autorização básica do Google:

Para mostrar aos usuários um card de autorização básica, retorne o objeto
AuthorizationError
. O código a seguir mostra um exemplo de objeto
AuthorizationError
:
Apps Script
CardService.newAuthorizationException() .setAuthorizationUrl('AUTHORIZATION_URL') .setResourceDisplayName('RESOURCE_DISPLAY_NAME') .throwException();
JSON
Retorne a seguinte resposta JSON:
{
"basic_authorization_prompt": {
"authorization_url": "AUTHORIZATION_URL",
"resource": "RESOURCE_DISPLAY_NAME"
}
}
Substitua:
AUTHORIZATION_URL
: o URL do app da Web que processa a autorização.RESOURCE_DISPLAY_NAME
: o nome de exibição do recurso ou serviço protegido. Esse nome é exibido ao usuário na solicitação de autorização. Por exemplo, se seuRESOURCE_DISPLAY_NAME
forExample Account
, a solicitação vai dizer: "Este complemento quer mostrar mais informações, mas é necessário autorizar o acesso à sua Conta de exemplo".
Depois de concluir a autorização, o usuário vai receber uma solicitação para atualizar o complemento e acessar o recurso protegido.
Cartões de autorização de devolução no Google Chat
Se o complemento estender o Google Chat e o usuário
executar o complemento no Google Chat, ele poderá concluir o processo de autorização
sem uma atualização manual. O Google Chat oferece suporte à nova tentativa automática da
execução anterior se o
gatilho
for Mensagem, Adicionado ao espaço ou Comando do app. Para esses gatilhos, o
complemento recebe completeRedirectUri
no
payload do evento.
É necessário codificar completeRedirectUri
no URL de configuração para acionar
a nova tentativa automática. O redirecionamento para esse URL indica ao Google Chat que a
solicitação de configuração foi atendida e permite que o Google Chat tente novamente a
execução anterior.
Quando um usuário é redirecionado para o configCompleteRedirectUrl
fornecido na mensagem original, o Google Chat realiza as seguintes etapas:
- Apaga o comando mostrado ao usuário que iniciou a ação.
- Envia o objeto de evento original para o mesmo complemento uma segunda vez.
Se você não codificar completeRedirectUri
no URL de configuração, o usuário ainda poderá concluir o fluxo de autorização. No entanto, o Google Chat não tenta executar novamente a
execução anterior, e o usuário precisa invocar manualmente o
complemento de novo.
O exemplo de código a seguir mostra como um app de chat pode solicitar credenciais OAuth2 off-line, armazená-las em um banco de dados e usá-las para fazer chamadas de API com autenticação de usuário.
Cartão de autorização personalizado
Para modificar a solicitação de autorização, crie um card personalizado para a experiência de login do seu serviço.
Se você estiver publicando seu complemento publicamente, use um cartão de autorização personalizado para todos os aplicativos host do Google Workspace, exceto o Chat. Para saber mais sobre os requisitos de publicação do Google Workspace Marketplace, consulte Sobre a análise de apps.
O card retornado precisa fazer o seguinte:
- Deixe claro para o usuário que o complemento está pedindo permissão para acessar um serviço que não é do Google em nome dele.
- Deixe claro o que o complemento pode fazer se autorizado.
- Ter um botão ou widget semelhante que leve o usuário ao URL de autorização do serviço. Verifique se a função do widget está óbvia para o usuário.
- O widget acima precisa usar a configuração
OnClose.RELOAD
no objetoOpenLink
para garantir que o complemento seja recarregado depois que a autorização for recebida. - Todos os links abertos na solicitação de autorização precisam usar HTTPS.
A imagem a seguir mostra um exemplo de card de autorização personalizado para a página inicial de um complemento. O card inclui um logotipo, uma descrição e um botão de login:

O código a seguir mostra como usar este exemplo de card personalizado:
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
Retorne a seguinte resposta 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"
}
}
]
}
]
}
}
]
}
}
}
Substitua:
LOGO_URL
: o URL de um logotipo ou imagem. Precisa ser um URL público.LOGO_ALT_TEXT
: texto alternativo para o logotipo ou a imagem, comoCymbal Labs Logo
.DESCRIPTION
: uma call-to-action para os usuários fazerem login, comoSign in to get started
.- Para atualizar o botão de login:
AUTHORIZATION_URL
: o URL do app da Web que processa a autorização.- Opcional: para mudar a cor do botão, atualize os valores de ponto flutuante RGBA do campo
color
. No Apps Script, atualize o métodosetBackgroundColor()
usando valores hexadecimais.
TEXT_SIGN_UP
: um texto que pede aos usuários para criar uma conta se eles não tiverem uma. Por exemplo,New to Cymbal Labs? <a href=\"https://www.example.com/signup\">Sign up</a> here
.
Gerenciar logins de terceiros nos apps do Google Workspace
Um uso comum dos complementos do Google Workspace é fornecer uma interface para interagir com um sistema de terceiros em um aplicativo host do Google Workspace.
Os sistemas de terceiros geralmente exigem que o usuário faça login com um ID de usuário, uma senha ou outra credencial. Quando um usuário faz login no seu serviço de terceiros enquanto usa um host do Google Workspace, é preciso garantir que ele não precise fazer login de novo ao mudar para outro host do Google Workspace.
Se você estiver criando no Apps Script, poderá evitar solicitações de login repetidas com propriedades do usuário ou tokens de ID. Elas são explicadas nas seções a seguir.
Propriedades do usuário
É possível armazenar os dados de login de um usuário nas propriedades do usuário do Apps Script. Por exemplo, você pode criar seu próprio JSON Web Token (JWT) no serviço de login e registrar isso em uma propriedade do usuário ou registrar o nome de usuário e a senha do serviço.
As propriedades do usuário são definidas de forma que só possam ser acessadas por ele no script do complemento. Outros usuários e scripts não podem acessar essas propriedades. Veja PropertiesService
para mais detalhes.
Tokens de ID
Você pode usar um token de ID do Google como a credencial de login do seu serviço. Essa é uma maneira de fazer o logon único. Os usuários já estão conectados ao Google porque estão em um app host do Google.
Exemplo de configuração do OAuth que não é do Google
O exemplo de código do Apps Script a seguir mostra como configurar um complemento para usar uma API que não é do Google e exige OAuth. Esta amostra usa a biblioteca OAuth2 para Apps Script para criar um serviço de acesso à API.
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();
}