

اگر افزونهی Google Workspace شما به یک سرویس یا API شخص ثالث که نیاز به مجوز دارد متصل شود، افزونه میتواند کاربران را وادار به ورود و تأیید دسترسی کند.
این صفحه نحوه احراز هویت کاربران با استفاده از یک جریان مجوز (مانند OAuth) را توضیح میدهد که شامل مراحل زیر است:
- تشخیص زمان نیاز به مجوز.
- یک رابط کارتی را برگردانید که کاربران را به ورود به سرویس ترغیب میکند.
- افزونه را بهروزرسانی کنید تا کاربران بتوانند به سرویس یا منبع محافظتشده دسترسی پیدا کنند.
اگر افزونه شما فقط به هویت کاربر نیاز دارد، میتوانید مستقیماً با استفاده از شناسه Google Workspace یا آدرس ایمیل آنها، کاربران را احراز هویت کنید. برای استفاده از آدرس ایمیل برای احراز هویت، به اعتبارسنجی درخواستهای JSON مراجعه کنید. اگر افزونه خود را با استفاده از Google Apps Script ساختهاید، میتوانید با استفاده از کتابخانه OAuth2 برای Google Apps Script ( نسخه OAuth1 نیز وجود دارد)، این فرآیند را آسانتر کنید.
تشخیص دهید که مجوز لازم است
هنگام استفاده از افزونه شما، ممکن است کاربران به دلایل مختلف، مانند موارد زیر، مجاز به دسترسی به یک منبع محافظتشده نباشند:
- توکن دسترسی برای اتصال به سرویس شخص ثالث هنوز ایجاد نشده یا منقضی شده است.
- توکن دسترسی، منبع درخواستی را پوشش نمیدهد.
- توکن دسترسی، محدودههای مورد نیاز درخواست را پوشش نمیدهد.
افزونه شما باید این موارد را تشخیص دهد تا کاربران بتوانند وارد سیستم شوند و به سرویس شما دسترسی پیدا کنند.
اگر در حال ساخت برنامه با Apps Script هستید، تابع hasAccess() کتابخانه OAuth میتواند به شما بگوید که آیا به یک سرویس دسترسی دارید یا خیر. از طرف دیگر، هنگام استفاده از درخواستهای UrlFetchApp fetch() ، میتوانید پارامتر muteHttpExceptions را روی true تنظیم کنید. این کار از ایجاد استثنا در صورت عدم موفقیت درخواست جلوگیری میکند و به شما امکان میدهد کد پاسخ درخواست و محتوای شیء HttpResponse بازگشتی را بررسی کنید.
از کاربران بخواهید که به سرویس شما وارد شوند
وقتی افزونه شما تشخیص میدهد که نیاز به مجوز است، باید یک رابط کارت را برگرداند تا کاربران را به ورود به سرویس ترغیب کند. کارت ورود باید کاربران را به تکمیل فرآیند احراز هویت و مجوز شخص ثالث در زیرساخت شما هدایت کند.
هنگام ساخت افزونه خود با استفاده از نقاط پایانی HTTP، توصیه میکنیم برنامه مقصد را با ورود به سیستم گوگل محافظت کنید و شناسه کاربر را با استفاده از توکن هویتی که هنگام ورود به سیستم صادر شده است، دریافت کنید. این زیرعنوان حاوی شناسه منحصر به فرد کاربر است و میتواند با شناسه افزونه شما مرتبط باشد.
ساخت و بازگرداندن کارت ورود به سیستم
برای کارت ورود به سیستم سرویس خود، میتوانید از کارت مجوز پایه گوگل استفاده کنید، یا میتوانید یک کارت را برای نمایش اطلاعات اضافی، مانند لوگوی سازمان خود، سفارشی کنید . اگر افزونه خود را به صورت عمومی منتشر میکنید، باید از یک کارت سفارشی استفاده کنید.
کارت مجوز پایه
تصویر زیر نمونهای از کارت مجوز پایه گوگل را نشان میدهد:


برای اینکه به کاربران یک کارت مجوز پایه بدهید، باید شیء AuthorizationError برگردانید. کد زیر نمونهای از یک شیء AuthorizationError نشان میدهد:
اسکریپت برنامهها
CardService.newAuthorizationException()
.setAuthorizationUrl('AUTHORIZATION_URL')
.setResourceDisplayName('RESOURCE_DISPLAY_NAME')
.throwException();جیسون
پاسخ JSON زیر را برگردانید:
{
"basic_authorization_prompt": {
"authorization_url": "AUTHORIZATION_URL",
"resource": "RESOURCE_DISPLAY_NAME"
}
}
موارد زیر را جایگزین کنید:
-
AUTHORIZATION_URL: آدرس اینترنتی برنامه وب که مجوزها را مدیریت میکند. -
RESOURCE_DISPLAY_NAME: نام نمایشی برای منبع یا سرویس محافظتشده. این نام در اعلان مجوز به کاربر نمایش داده میشود. برای مثال، اگرRESOURCE_DISPLAY_NAMEشماExample Accountباشد، اعلان میگوید: «این افزونه میخواهد اطلاعات بیشتری را نشان دهد، اما برای دسترسی به Example Account شما نیاز به تأیید دارد.»
پس از تکمیل مجوز، از کاربر خواسته میشود که افزونه را برای دسترسی به منبع محافظتشده بهروزرسانی کند.
کارتهای مجوز را در گوگل چت برگردانید
اگر افزونه شما Google Chat را گسترش دهد و کاربر آن را در Google Chat اجرا کند، میتواند فرآیند مجوزدهی را بدون نیاز به رفرش دستی تکمیل کند. اگر تریگر Message ، Added to space یا App command باشد، Google Chat از تلاش مجدد خودکار برای اجرای قبلی پشتیبانی میکند. برای این تریگرها، افزونه شما completeRedirectUri در event payload دریافت میکند. برای شروع تلاش مجدد خودکار، باید completeRedirectUri در URL پیکربندی خود کدگذاری کنید. هدایت به این URL به Google Chat نشان میدهد که درخواست پیکربندی انجام شده است و به Google Chat اجازه میدهد تا اجرای قبلی را دوباره امتحان کند.
وقتی کاربر با موفقیت به configCompleteRedirectUrl ارائه شده در پیام اصلی هدایت میشود، گوگل چت مراحل زیر را انجام میدهد:
- اعلان نمایش داده شده به کاربر آغازگر را پاک میکند.
- شیء رویداد اصلی را برای بار دوم به همان افزونه ارسال میکند.
اگر completeRedirectUri در URL پیکربندی کدگذاری نکنید، کاربر همچنان میتواند جریان مجوز را تکمیل کند. با این حال، Google Chat اجرای قبلی را دوباره امتحان نمیکند و کاربر باید دوباره افزونه شما را به صورت دستی فراخوانی کند.
نمونه کد زیر نشان میدهد که چگونه یک برنامه چت میتواند اعتبارنامههای آفلاین OAuth2 را درخواست کند، آنها را در یک پایگاه داده ذخیره کند و از آنها برای برقراری تماسهای API با احراز هویت کاربر استفاده کند.
اسکریپت برنامهها
نود جی اس
پایتون
جاوا
کارت مجوز سفارشی
برای تغییر اعلان مجوز، میتوانید یک کارت سفارشی برای تجربه ورود به سیستم سرویس خود ایجاد کنید.
اگر افزونه خود را به صورت عمومی منتشر میکنید، باید از یک کارت مجوز سفارشی برای همه برنامههای میزبان Google Workspace به جز Chat استفاده کنید. برای کسب اطلاعات بیشتر در مورد الزامات انتشار برای Google Workspace Marketplace، به «درباره بررسی برنامه» مراجعه کنید.
کارت برگشتی باید موارد زیر را انجام دهد:
- برای کاربر روشن کنید که افزونه از طرف او درخواست دسترسی به یک سرویس غیر گوگلی را دارد.
- مشخص کنید که افزونه در صورت مجاز بودن، چه کارهایی میتواند انجام دهد.
- شامل یک دکمه یا ویجت مشابه باشد که کاربر را به URL مجوز سرویس هدایت کند. مطمئن شوید که عملکرد این ویجت برای کاربر واضح است.
- ویجت فوق باید از تنظیم
OnClose.RELOADدر شیءOpenLinkخود استفاده کند تا اطمینان حاصل شود که افزونه پس از دریافت مجوز، مجدداً بارگذاری میشود. - تمام لینکهایی که از طریق اعلان مجوز باز میشوند باید از 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 زیر را برگردانید:
{
"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 هستید، میتوانید با استفاده از ویژگیهای کاربر یا توکنهای شناسه، از درخواستهای مکرر ورود به سیستم جلوگیری کنید. این موارد در بخشهای بعدی توضیح داده شدهاند.
ویژگیهای کاربر
شما میتوانید دادههای ورود کاربر را در ویژگیهای کاربر Apps Script ذخیره کنید. برای مثال، میتوانید JSON Web Token (JWT) خود را از سرویس ورود آنها ایجاد کنید و آن را در یک ویژگی کاربر ثبت کنید، یا نام کاربری و رمز عبور سرویس آنها را ثبت کنید.
ویژگیهای کاربر به گونهای تنظیم شدهاند که فقط توسط آن کاربر در اسکریپت افزونه شما قابل دسترسی هستند. سایر کاربران و اسکریپتهای دیگر نمیتوانند به این ویژگیها دسترسی داشته باشند. برای جزئیات بیشتر به PropertiesService مراجعه کنید.
توکنهای شناسایی
شما میتوانید از یک توکن شناسه گوگل (Google ID token) به عنوان اعتبارنامه ورود به سرویس خود استفاده کنید. این روشی برای دستیابی به ورود یکپارچه (single sign-on) است. کاربران از قبل به گوگل وارد شدهاند زیرا در یک برنامه میزبان گوگل هستند.
مثال پیکربندی OAuth غیر گوگل
نمونه کد Apps Script زیر نحوه پیکربندی یک افزونه برای استفاده از یک API غیر گوگلی که نیاز به 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.
*/
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();
}