اگر برافزای Google Workspace شما به سرویس یا میانای برنامهسازی کاربردی طرف سومی متصل میشود که به مجوز نیاز دارد، برافزا میتواند از کاربران بخواهد به سیستم وارد شوند و دسترسی را مجاز کنند.
این صفحه نحوه اصالتسنجی کاربران بااستفاده از جریان صدور مجوز (مثل OAuth) را توضیح میدهد که شامل مراحل زیر است:
- تشخیص زمانی که مجوز لازم است.
- واسط کارتی را برمیگرداند که از کاربران میخواهد به سیستم سرویس وارد شوند.
- برافزایی را بازآوری کنید تا کاربران بتوانند به خدمات یا منبع محافظتشده دسترسی پیدا کنند.
اگر برافزای شما فقط به هویت کاربر نیاز دارد، میتوانید کاربران را مستقیماً بااستفاده از شناسه Google Workspace یا نشانی ایمیلشان اصالتسنجی کنید. برای استفاده از نشانی ایمیل برای اصالتسنجی، اعتبارسنجی درخواستهای JSON را ببینید. اگر برافزایتان را بااستفاده از Google Apps Script ساختهاید، بااستفاده از کتابخانه OAuth2 برای Google Apps Script (نسخه OAuth1 نیز وجود دارد) میتوانید این فرایند را آسانتر کنید.
تشخیص اینکه مجوز لازم است
هنگام استفاده از برافزا، ممکن است کاربران به دلایل مختلفی برای دسترسی به منبع محافظتشده مجاز نباشند، مثلاً به دلایل زیر:
- هنوز کد دسترسی برای اتصال به سرویس طرف سوم تولید نشده است یا منقضی شده است.
- کد دسترسی منبع درخواستی را پوشش نمیدهد.
- کد دسترسی دامنههای موردنیاز درخواست را پوشش نمیدهد.
برافزای شما باید این موارد را تشخیص دهد تا کاربران بتوانند به سیستم وارد شوند و به سرویس شما دسترسی پیدا کنند.
اگر در Apps Script میسازید، تابع کتابخانه OAuth
hasAccess میتواند به شما بگوید که آیا به سرویسی دسترسی دارید یا نه.
یا اینکه هنگام استفاده از درخواستهای
UrlFetchApp.fetch
، میتوانید پارامتر muteHttpExceptions را روی true تنظیم کنید. این کار باعث میشود که درخواست درصورت ناموفق بودن استثنایی ایجاد نکند و به شما امکان میدهد کد پاسخ و محتوای درخواست را در شیء HttpResponse برگشتی بررسی کنید.
از کاربران بخواهید به سیستم سرویس شما وارد شوند
وقتی برافزا تشخیص میدهد که مجوز لازم است، برافزا باید رابط کارت را برگرداند تا از کاربران بخواهد به سیستم سرویس وارد شوند. کارت ورود به سیستم باید کاربران را به زیرساخت شما هدایت کند تا فرایند اصالتسنجی و صدور مجوز طرف سوم را تکمیل کنند.
هنگام ساختن برافزای خود بااستفاده از نقاط پایانی HTTP، توصیه میکنیم که برنامه مقصد را با ورود به سیستم با Google محافظت کنید و شناسه کاربر را بااستفاده از نشانه هویت صادرشده درطول ورود به سیستم دریافت کنید. ادعای فرعی حاوی شناسه یکتای کاربر است و میتواند با شناسه افزونه شما مرتبط شود.
.ساختن و برگرداندن کارت ورود به سیستم
برای کارت ورود به سیستم سرویس خود، میتوانید از کارت مجوز اولیه Google استفاده کنید، یا میتوانید کارتی را سفارشیسازی کنید تا اطلاعات اضافی، مانند نشانواره سازمانتان، را نمایش دهد. اگر برافزایتان را بهصورت عمومی منتشر میکنید، باید از کارت سفارشی استفاده کنید.
کارت مجوز پایه
تصویر زیر نمونهای از کارت مجوز پایه Google را نشان میدهد:
برای اینکه کاربران با کارت مجوز پایه ترغیب شوند، باید شیء
AuthorizationError را برگردانید. کد زیر نمونهای از
AuthorizationError شیء را نشان میدهد:
Apps Script
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 Chat
اگر برافزایتان Google Chat را گسترش دهد و کاربر آن را در Google Chat اجرا کند، کاربر میتواند فرایند
صدور مجوز را بدون بازآوری دستی تکمیل کند. اگر راهانداز
پیام، افزودهشده به فضا، یا فرمان برنامه باشد، Google Chat از تلاش مجدد خودکار برای اجرای قبلی پشتیبانی میکند. برای این راهاندازها، برافزایتان completeRedirectUri را در
بار رویداد دریافت میکند.
برای راهاندازی مجدد خودکار، باید completeRedirectUri را در نشانی وب پیکربندی خود کدبندی کنید. هدایت به این نشانی وب به Google Chat اطلاع میدهد که درخواست پیکربندی برآورده شده است و به Google Chat اجازه میدهد اجرای قبلی را دوباره امتحان کند.
وقتی کاربر باموفقیت به configCompleteRedirectUrl
ارائهشده در پیام اصلی هدایت میشود، Google Chat مراحل زیر را انجام میدهد:
- پیامواره نمایشدادهشده به کاربر آغازگر را پاک میکند.
- شیء رویداد اصلی را برای بار دوم به همان برافزایی ارسال میکند.
اگر completeRedirectUri را در نشانی وب پیکربندی کدبندی نکنید، کاربر همچنان میتواند
جریان مجوز را تکمیل کند. بااینحال، Google Chat اجرای قبلی را دوباره امتحان نمیکند و کاربر باید بهصورت دستی افزونه را دوباره فراخوانی کند.
نمونه کد زیر نشان میدهد که چگونه یک برنامه Chat میتواند اعتبارنامههای OAuth2 آفلاین را درخواست کند، آنها را در پایگاه داده ذخیره کند، و از آنها برای برقراری تماسهای API با اصالتسنجی کاربر استفاده کند.
Apps Script
Node.js
Python
جاوا
کارت مجوز سفارشی
برای اصلاح پیامواره مجوز، میتوانید کارت سفارشی برای تجربه ورود به سیستم سرویس خود ایجاد کنید.
اگر برافزایتان را بهصورت عمومی منتشر میکنید، باید برای همه برنامههای میزبان Google Workspace بهجز Chat از کارت مجوز سفارشی استفاده کنید. برای آشنایی بیشتر با الزامات انتشار در Google Workspace Marketplace، به درباره بررسی برنامه مراجعه کنید.
کارت برگشتی باید موارد زیر را انجام دهد:
- بهطور شفاف به کاربر اطلاع دهید که برافزا درخواست میکند اجازه دسترسی به سرویس غیرGoogle را ازطرف او داشته باشد.
- اگر برافزا مجاز شد، بهوضوح توضیح دهید که چه کارهایی میتواند انجام دهد.
- حاوی دکمه یا ابزارهای مشابه باشد که کاربر را به نشانی وب مجوزدهی سرویس هدایت کند. مطمئن شوید که عملکرد این ابزارک برای کاربر واضح باشد.
- ابزارک قبلی باید از تنظیم
OnClose.RELOADدر شیءOpenLinkخود استفاده کند تا مطمئن شود که پساز دریافت مجوز، برافزا دوباره بار میشود. - همه پیوندهایی که از پیامواره مجوز باز میشوند باید از HTTPS استفاده کنند.
تصویر زیر نمونهای از کارت مجوز سفارشی برای صفحه اصلی برافزا را نشان میدهد. کارت شامل نشانواره، شرح، و دکمه ورود به سیستم است:
کد زیر نحوه استفاده از این مثال کارت سفارشی را نشان میدهد:
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
پاسخ 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: نشانی وب نشانواره یا تصویر. باید نشانی وب عمومی باشد.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» (JWT) خودتان را از سرویس ورود به سیستم آنها بسازید و آن را در دارایی کاربر ضبط کنید، یا نام کاربری و گذرواژه سرویس آنها را ضبط کنید.
داراییهای کاربر بهگونهای محدود شدهاند که فقط آن کاربر میتواند
در اسکریپت برافزای شما به آنها دسترسی داشته باشد. کاربران دیگر و
نوشتههای دیگر نمیتوانند به این داراییها دسترسی داشته باشند. برای جزئیات بیشتر،
PropertiesService
را ببینید.
دادهواحد شناسه
میتوانید از یک کد شناسایی Google بهعنوان اطلاعات اعتباری ورود به سیستم برای سرویس خود استفاده کنید. این روشی برای دستیابی به یکبار ورود است. کاربران ازقبل به سیستم Google وارد شدهاند زیرا در برنامه میزبان Google هستند.
نمونه پیکربندی OAuth غیر Google
نمونه کد Apps Script زیر نشان میدهد که چگونه یک برافزا را برای استفاده از یک API غیر Google که به OAuth نیاز دارد پیکربندی کنید. این نمونه از کتابخانه OAuth2 برای Apps Script برای ساختن سرویسی جهت دسترسی به 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();
}