به Google Identity Services مهاجرت کنید

نمای کلی

برای دریافت توکن دسترسی به ازای هر کاربر جهت فراخوانی APIهای گوگل، گوگل چندین کتابخانه جاوا اسکریپت ارائه می‌دهد:

این راهنما دستورالعمل‌هایی برای مهاجرت از این کتابخانه‌ها به کتابخانه سرویس‌های هویت گوگل ارائه می‌دهد.

با دنبال کردن این راهنما، شما:

  • کتابخانه منسوخ‌شده‌ی Platform Library را با کتابخانه‌ی Identity Services جایگزین کنید، و
  • اگر از کتابخانه کلاینت API استفاده می‌کنید، ماژول منسوخ gapi.auth2 ، متدها و اشیاء آن را حذف کرده و آنها را با معادل‌های سرویس‌های هویت جایگزین کنید.

برای شرح تغییرات کتابخانه جاوا اسکریپت Identity Services، بخش مرور کلی و نحوه عملکرد مجوزدهی کاربر را مطالعه کنید تا اصطلاحات و مفاهیم کلیدی را مرور کنید.

اگر به دنبال احراز هویت برای ثبت نام و ورود کاربر هستید، به جای آن، به بخش مهاجرت از ورود به سیستم با گوگل مراجعه کنید.

جریان مجوز خود را مشخص کنید

دو جریان مجوزدهی کاربر وجود دارد: ضمنی و کد مجوزدهی.

برنامه وب خود را بررسی کنید تا نوع جریان مجوز مورد استفاده را شناسایی کنید.

نشانه‌هایی که نشان می‌دهد برنامه وب شما از جریان ضمنی استفاده می‌کند:

  • برنامه وب شما صرفاً مبتنی بر مرورگر است و هیچ پلتفرم بک‌اندی ندارد.
  • کاربر باید برای فراخوانی APIهای گوگل حضور داشته باشد، برنامه شما فقط از توکن‌های دسترسی استفاده می‌کند و نیازی به توکن‌های رفرش ندارد.
  • برنامه وب شما apis.google.com/js/api.js را بارگذاری می‌کند.
  • پیاده‌سازی شما بر اساس OAuth 2.0 برای برنامه‌های وب سمت کلاینت است.
  • برنامه شما از ماژول‌های gapi.client یا gapi.auth2 موجود در کتابخانه کلاینت API گوگل برای جاوا اسکریپت استفاده می‌کند.

نشانه‌هایی که نشان می‌دهد برنامه وب شما از جریان کد مجوز استفاده می‌کند:

  • پیاده‌سازی شما بر اساس موارد زیر است:

  • برنامه شما هم در مرورگر کاربر و هم در پلتفرم بک‌اند شما اجرا می‌شود.

  • پلتفرم بک‌اند شما میزبان یک نقطه پایانی کد مجوز است.

  • پلتفرم بک‌اند شما، APIهای گوگل را از طرف کاربران و بدون نیاز به حضور آنها فراخوانی می‌کند، که به عنوان حالت آفلاین نیز شناخته می‌شود.

  • توکن‌های رفرش توسط پلتفرم بک‌اند شما مدیریت و ذخیره می‌شوند.

در برخی موارد، کدبیس شما ممکن است از هر دو جریان پشتیبانی کند.

یک جریان مجوز انتخاب کنید

قبل از شروع مهاجرت، باید مشخص کنید که آیا ادامه دادن به جریان فعلی یا اتخاذ یک جریان متفاوت، به بهترین شکل نیازهای شما را برآورده می‌کند.

برای درک تفاوت‌های کلیدی و بده‌بستان‌های بین این دو جریان ، انتخاب یک جریان مجوزدهی را بررسی کنید.

در بیشتر موارد، جریان کد مجوز توصیه می‌شود زیرا بالاترین سطح امنیت کاربر را ارائه می‌دهد. پیاده‌سازی این جریان همچنین پلتفرم شما را قادر می‌سازد تا قابلیت‌های آفلاین جدیدی مانند دریافت به‌روزرسانی‌ها را برای اطلاع‌رسانی به کاربران در مورد تغییرات قابل توجه در تقویم، عکس‌ها و اشتراک‌هایشان اضافه کند.

با استفاده از انتخابگرها، یک جریان مجوزدهی انتخاب کنید .

جریان ضمنی

دریافت یک توکن دسترسی برای استفاده در مرورگر در زمانی که کاربر حضور دارد.

مثال‌های جریان ضمنی، برنامه‌های وب را قبل و بعد از مهاجرت به سرویس‌های هویت نشان می‌دهد.

جریان کد مجوز

یک کد مجوز برای هر کاربر که توسط گوگل صادر شده است، به پلتفرم بک‌اند شما ارسال می‌شود، جایی که با یک توکن دسترسی و توکن رفرش مبادله می‌شود.

نمونه‌هایی از جریان کد مجوز ، برنامه‌های وب را قبل و بعد از مهاجرت به سرویس‌های هویت نشان می‌دهد.

در سراسر این راهنما، دستورالعمل‌های فهرست‌شده با حروف پررنگ را برای افزودن ، حذف ، به‌روزرسانی یا جایگزینی قابلیت‌های موجود دنبال کنید.

تغییرات در برنامه وب درون مرورگر شما

این بخش، تغییراتی را که هنگام مهاجرت به کتابخانه جاوا اسکریپت سرویس‌های هویت گوگل (Google Identity Services) در برنامه وب درون مرورگر خود ایجاد خواهید کرد، بررسی می‌کند.

کد آسیب‌دیده را شناسایی و آزمایش کنید

یک کوکی اشکال‌زدایی می‌تواند به یافتن کد آسیب‌دیده و آزمایش رفتار پس از منسوخ شدن کمک کند.

در برنامه‌های بزرگ یا پیچیده، ممکن است پیدا کردن تمام کدهایی که تحت تأثیر منسوخ شدن ماژول gapi.auth2 قرار گرفته‌اند، دشوار باشد. برای ثبت استفاده فعلی از قابلیت‌هایی که به زودی منسوخ می‌شوند در کنسول، مقدار کوکی G_AUTH2_MIGRATION را روی informational تنظیم کنید. در صورت تمایل، یک دونقطه و به دنبال آن یک مقدار کلیدی اضافه کنید تا در حافظه نشست نیز ثبت شود. پس از ورود به سیستم و دریافت اعتبارنامه‌ها، گزارش‌های جمع‌آوری‌شده را برای تجزیه و تحلیل بعدی به یک backend بررسی یا ارسال کنید. به عنوان مثال، informational:showauth2use مبدا و URL را در یک کلید ذخیره‌سازی نشست به نام showauth2use ذخیره می‌کند.

برای تأیید رفتار برنامه زمانی که ماژول gapi.auth2 دیگر بارگیری نمی‌شود، مقدار کوکی G_AUTH2_MIGRATION را روی enforced تنظیم کنید. این کار امکان آزمایش رفتار پس از منسوخ شدن را قبل از تاریخ اجرا فراهم می‌کند.

مقادیر ممکن کوکی G_AUTH2_MIGRATION :

  • enforced gapi.auth2 بارگذاری نشود.
  • گزارش informational استفاده از قابلیت‌های منسوخ‌شده را در کنسول جاوااسکریپت ثبت می‌کند. همچنین وقتی نام کلید اختیاری تنظیم می‌شود، آن را در حافظه نشست ثبت می‌کند: informational:key-name .

برای به حداقل رساندن تأثیر کاربر، توصیه می‌شود که ابتدا این کوکی را به صورت محلی در طول توسعه و آزمایش، قبل از استفاده در محیط‌های عملیاتی، تنظیم کنید.

کتابخانه‌ها و ماژول‌ها

ماژول gapi.auth2 احراز هویت کاربر برای ورود به سیستم و جریان ضمنی برای مجوزدهی را مدیریت می‌کند. این ماژول منسوخ شده و اشیاء و متدهای آن را با کتابخانه Google Identity Services جایگزین کنید.

با گنجاندن کتابخانه Identity Services در سند خود، آن را به برنامه وب خود اضافه کنید :

<script src="https://accounts.google.com/gsi/client" async defer></script>

هر نمونه‌ای از بارگذاری ماژول auth2 را با استفاده از gapi.load('auth2', function) حذف کنید .

کتابخانه Google Identity Services جایگزین ماژول gapi.auth2 شده است. شما می‌توانید با خیال راحت به استفاده از ماژول gapi.client از کتابخانه Google API Client برای جاوا اسکریپت ادامه دهید و از مزایای ایجاد خودکار متدهای JS قابل فراخوانی از یک سند اکتشاف، دسته‌بندی چندین فراخوانی API و قابلیت مدیریت CORS آن بهره‌مند شوید.

کوکی‌ها

مجوز کاربر نیازی به استفاده از کوکی‌ها ندارد.

برای جزئیات بیشتر در مورد نحوه استفاده احراز هویت کاربر از کوکی‌ها و نحوه استفاده گوگل از کوکی‌ها برای استفاده سایر محصولات و سرویس‌های گوگل، به بخش «مهاجرت از ورود به سیستم با گوگل» مراجعه کنید.

مدارک تحصیلی

سرویس‌های هویت گوگل، احراز هویت کاربر و مجوزدهی را به دو عملیات مجزا تقسیم می‌کنند و اعتبارنامه‌های کاربر نیز از هم جدا هستند: توکن شناسه‌ای که برای شناسایی کاربر استفاده می‌شود، جدا از توکن دسترسی که برای مجوزدهی استفاده می‌شود، بازگردانده می‌شود.

برای مشاهده این تغییرات، به نمونه اعتبارنامه‌ها مراجعه کنید.

جریان ضمنی

با حذف مدیریت پروفایل کاربر از جریان‌های مجوز، احراز هویت و مجوزدهی کاربر را از هم جدا کنید.

این ارجاعات جاوا اسکریپت کلاینت ورود به سیستم گوگل را حذف کنید :

روش‌ها

  • GoogleUser.getBasicProfile()
  • GoogleUser.getId()

جریان کد مجوز

سرویس‌های هویت، اعتبارنامه‌های درون مرورگر را به توکن شناسه و توکن دسترسی تفکیک می‌کنند. این تغییر در مورد اعتبارنامه‌هایی که از طریق فراخوانی‌های مستقیم به نقاط انتهایی Google OAuth 2.0 از پلتفرم backend شما یا از طریق کتابخانه‌هایی که روی یک سرور امن روی پلتفرم شما مانند Google APIs Node.js Client اجرا می‌شوند، اعمال نمی‌شود.

حالت جلسه

پیش از این، Google Sign-In به شما کمک می‌کرد تا وضعیت ورود کاربر را با استفاده از موارد زیر مدیریت کنید:

شما مسئول مدیریت وضعیت ورود به سیستم و جلسات کاربر در برنامه وب خود هستید.

این ارجاعات جاوا اسکریپت کلاینت ورود به سیستم گوگل را حذف کنید :

اشیاء:

  • gapi.auth2.SignInOptions

روش‌ها:

  • GoogleAuth.attachClickHandler()
  • GoogleAuth.isSignedIn()
  • GoogleAuth.isSignedIn.get()
  • GoogleAuth.isSignedIn.listen()
  • GoogleAuth.signIn()
  • GoogleAuth.signOut()
  • GoogleAuth.currentUser.get()
  • GoogleAuth.currentUser.listen()
  • GoogleUser.isSignedIn()

پیکربندی کلاینت

برنامه وب خود را به‌روزرسانی کنید تا یک کلاینت توکن برای جریان کد ضمنی یا مجوزدهی راه‌اندازی شود.

این ارجاعات جاوا اسکریپت کلاینت ورود به سیستم گوگل را حذف کنید :

اشیاء:

  • gapi.auth2.ClientConfig
  • gapi.auth2.OfflineAccessOptions

روش‌ها:

  • gapi.auth2.getAuthInstance()
  • GoogleUser.grant()

جریان ضمنی

یک شیء TokenClientConfig اضافه کنید و initTokenClient() را برای پیکربندی برنامه وب خود فراخوانی کنید، مانند مثال در initialize a token client .

جایگزین کردن ارجاعات کلاینت جاوا اسکریپت Google Sign-In با سرویس‌های هویت گوگل :

اشیاء:

  • gapi.auth2.AuthorizeConfig به همراه TokenClientConfig

روش‌ها:

  • gapi.auth2.init() به همراه google.accounts.oauth2.initTokenClient()

پارامترها:

  • gapi.auth2.AuthorizeConfig.login_hint به همراه TokenClientConfig.login_hint .
  • gapi.auth2.GoogleUser.getHostedDomain() به همراه TokenClientConfig.hd

جریان کد مجوز

یک شیء CodeClientConfig اضافه کنید و initCodeClient() را برای پیکربندی برنامه وب خود فراخوانی کنید، مانند مثال در مقداردهی اولیه یک Code Client .

هنگام تغییر از جریان کد ضمنی به کد مجوز:

حذف ارجاعات کلاینت جاوا اسکریپت ورود به سیستم گوگل

اشیاء:

  • gapi.auth2.AuthorizeConfig

روش‌ها:

  • gapi.auth2.init()

پارامترها:

  • gapi.auth2.AuthorizeConfig.login_hint
  • gapi.auth2.GoogleUser.getHostedDomain()

درخواست توکن

یک حرکت کاربر، مانند کلیک روی دکمه، درخواستی ایجاد می‌کند که منجر به بازگشت مستقیم توکن دسترسی به مرورگر کاربر با جریان ضمنی یا بازگشت به پلتفرم بک‌اند شما پس از تبادل کد مجوز هر کاربر با توکن دسترسی و توکن رفرش می‌شود.

جریان ضمنی

توکن‌های دسترسی را می‌توان در مرورگر دریافت و استفاده کرد، در حالی که کاربر وارد سیستم شده و یک جلسه فعال با گوگل دارد. برای حالت ضمنی، حتی اگر درخواست قبلی وجود داشته باشد، یک اشاره کاربر برای درخواست توکن دسترسی لازم است.

جایگزین کردن ارجاعات کلاینت جاوا اسکریپت ورود به سیستم گوگل : با سرویس‌های هویت گوگل :

روش‌ها:

  • gapi.auth2.authorize() به همراه TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() به همراه TokenClient.requestAccessToken()

یک لینک یا دکمه برای فراخوانی requestAccessToken() اضافه کنید تا جریان UX پاپ‌آپ برای درخواست توکن دسترسی یا دریافت توکن جدید پس از انقضای توکن موجود، آغاز شود.

کدبیس خود را به این صورت به‌روزرسانی کنید :

  • جریان توکن OAuth 2.0 را با requestAccessToken() فعال کنید.
  • با استفاده از requestAccessToken و OverridableTokenClientConfig از احراز هویت افزایشی پشتیبانی کنید تا یک درخواست برای چندین دامنه را به چندین درخواست کوچکتر تقسیم کنید.
  • وقتی توکن موجود منقضی یا لغو شد، یک توکن جدید درخواست کنید.

کار با چندین scope ممکن است نیاز به تغییرات ساختاری در کدبیس شما داشته باشد تا درخواست دسترسی به scopeها فقط در صورت نیاز و نه به طور همزمان، انجام شود. این به عنوان مجوز افزایشی شناخته می‌شود. هر درخواست باید تا حد امکان شامل تعداد scopeهای کمتری باشد و در حالت ایده‌آل، یک scope واحد. برای اطلاعات بیشتر در مورد نحوه به‌روزرسانی برنامه خود برای مجوز افزایشی، به نحوه مدیریت رضایت کاربر مراجعه کنید.

وقتی یک توکن دسترسی منقضی می‌شود، ماژول gapi.auth2 به طور خودکار یک توکن دسترسی جدید و معتبر برای برنامه وب شما دریافت می‌کند. برای بهبود امنیت کاربر، این فرآیند به‌روزرسانی خودکار توکن توسط کتابخانه خدمات هویت گوگل پشتیبانی نمی‌شود. برنامه وب شما باید به‌روزرسانی شود تا یک توکن دسترسی منقضی شده را شناسایی کرده و درخواست یک توکن جدید کند. برای اطلاعات بیشتر به بخش مدیریت توکن مراجعه کنید.

جریان کد مجوز

یک لینک یا دکمه برای فراخوانی requestCode() اضافه کنید تا کد مجوز از گوگل درخواست شود. برای مثال، به Trigger OAuth 2.0 Code Flow مراجعه کنید.

برای اطلاعات بیشتر در مورد نحوه پاسخ به یک توکن دسترسی منقضی شده یا لغو شده، به بخش مدیریت توکن مراجعه کنید.

مدیریت توکن

قابلیت مدیریت خطا را اضافه کنید تا هنگام استفاده از توکن دسترسی منقضی شده یا لغو شده، فراخوانی‌های ناموفق Google API را شناسایی کرده و یک توکن دسترسی جدید و معتبر درخواست کند.

کد وضعیت HTTP با کد 401 Unauthorized و invalid_token توسط API های گوگل زمانی که یک توکن دسترسی منقضی شده یا لغو شده استفاده شود، بازگردانده می‌شود. برای مثال، به پاسخ توکن نامعتبر مراجعه کنید.

توکن‌های منقضی شده

توکن‌های دسترسی کوتاه‌مدت هستند و اغلب فقط برای چند دقیقه اعتبار دارند.

ابطال توکن

در هر زمانی، صاحب حساب گوگل می‌تواند رضایت قبلی اعطا شده را لغو کند. انجام این کار، توکن‌های دسترسی موجود و توکن‌های به‌روزرسانی را باطل می‌کند. لغو رضایت ممکن است از طریق پلتفرم شما با استفاده revoke() یا از طریق حساب گوگل انجام شود.

جایگزین کردن ارجاعات کلاینت جاوا اسکریپت ورود به سیستم گوگل : با سرویس‌های هویت گوگل :

روش‌ها:

  • getAuthInstance().disconnect() به همراه google.accounts.oauth2.revoke()
  • GoogleUser.disconnect() به همراه google.accounts.oauth2.revoke()

وقتی کاربری حساب کاربری خود را در پلتفرم شما حذف می‌کند، یا می‌خواهد رضایت خود را برای اشتراک‌گذاری داده‌ها با برنامه شما لغو کند، لغو revoke فراخوانی کنید.

گوگل زمانی که برنامه وب یا پلتفرم بک‌اند شما درخواست توکن دسترسی می‌کند، یک کادر محاوره‌ای رضایت به کاربر نمایش می‌دهد. به نمونه کادرهای محاوره‌ای رضایت که توسط گوگل به کاربران نمایش داده می‌شود، مراجعه کنید.

قبل از صدور توکن دسترسی به برنامه شما، یک نشست گوگل موجود و فعال برای درخواست رضایت کاربر و ثبت نتیجه لازم است. اگر نشست موجود از قبل ایجاد نشده باشد، ممکن است از کاربر خواسته شود که به یک حساب گوگل وارد شود.

ورود کاربر

کاربران می‌توانند در یک تب مرورگر جداگانه یا به صورت بومی از طریق یک مرورگر یا سیستم عامل وارد حساب گوگل خود شوند. توصیه می‌کنیم گزینه ورود با گوگل را به سایت خود اضافه کنید تا وقتی کاربر برای اولین بار برنامه شما را باز می‌کند، یک جلسه فعال بین حساب گوگل و مرورگر برقرار شود. انجام این کار این مزایا را ارائه می‌دهد:

  • تعداد دفعاتی که کاربر باید وارد سیستم شود را به حداقل می‌رساند، درخواست توکن دسترسی، فرآیند ورود به حساب گوگل را در صورتی که جلسه فعالی از قبل وجود نداشته باشد، آغاز می‌کند.
  • مستقیماً از فیلد email اعتبارنامه JWT ID Token به عنوان مقدار پارامتر login_hint در اشیاء CodeClientConfig یا TokenClientConfig استفاده کنید. این امر به ویژه در صورتی مفید است که پلتفرم شما سیستم مدیریت حساب کاربری نداشته باشد.
  • یک حساب گوگل را جستجو و با یک حساب کاربری محلی موجود در پلتفرم خود مرتبط کنید، که به کاهش حساب‌های تکراری در پلتفرم شما کمک می‌کند.
  • وقتی یک حساب کاربری جدید و محلی ایجاد می‌شود، دیالوگ‌ها و جریان ثبت نام شما می‌تواند به وضوح از دیالوگ‌ها و جریان‌های احراز هویت کاربر جدا شود، که این امر تعداد مراحل مورد نیاز را کاهش داده و نرخ انصراف را بهبود می‌بخشد.

پس از ورود به سیستم و قبل از صدور توکن دسترسی، کاربران باید رضایت خود را برای استفاده از محدوده‌های درخواستی شما ارائه دهند.

پس از رضایت، یک توکن دسترسی به همراه لیستی از محدوده‌های تأیید شده یا رد شده توسط کاربر بازگردانده می‌شود.

مجوزهای جزئی به کاربران اجازه می‌دهند تا محدوده‌های جداگانه را تأیید یا رد کنند. هنگام درخواست دسترسی به چندین محدوده، هر محدوده مستقل از سایر محدوده‌ها اعطا یا رد می‌شود. بر اساس انتخاب کاربر، برنامه شما به صورت انتخابی ویژگی‌ها و عملکردهایی را فعال می‌کند که به یک محدوده خاص بستگی دارند.

جریان ضمنی

جایگزین کردن ارجاعات کلاینت جاوا اسکریپت Google Sign-In با سرویس‌های هویت گوگل :

اشیاء:

  • gapi.auth2.AuthorizeResponse به همراه TokenClient.TokenResponse
  • gapi.auth2.AuthResponse به همراه TokenClient.TokenResponse

روش‌ها:

  • GoogleUser.hasGrantedScopes() به همراه google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() به همراه google.accounts.oauth2.hasGrantedAllScopes()

حذف ارجاعات کلاینت جاوا اسکریپت ورود به سیستم گوگل :

روش‌ها:

  • GoogleUser.getAuthResponse()

با دنبال کردن این مثال مجوزهای جزئی، برنامه وب خود را با hasGrantedAllScopes() و hasGrantedAnyScope() به‌روزرسانی کنید .

جریان کد مجوز

با دنبال کردن دستورالعمل‌های موجود در بخش مدیریت کد احراز هویت، یک نقطه پایانی کد احراز هویت را به پلتفرم بک‌اند خود به‌روزرسانی یا اضافه کنید .

پلتفرم خود را به‌روزرسانی کنید تا مراحل شرح داده شده در راهنمای «استفاده از مدل کد» را برای اعتبارسنجی درخواست و دریافت توکن دسترسی و توکن به‌روزرسانی دنبال کنید.

پلتفرم خود را به‌روزرسانی کنید تا ویژگی‌ها و قابلیت‌ها را بر اساس حوزه‌های اختصاصی که کاربر با پیروی از دستورالعمل‌های مربوط به مجوزدهی تدریجی تأیید کرده است، به صورت انتخابی فعال یا غیرفعال کند و حوزه‌های دسترسی اعطا شده توسط کاربر را بررسی کند .

مثال‌های جریان ضمنی

راه قدیمی

کتابخانه مشتری GAPI

نمونه‌ای از کتابخانه کلاینت API گوگل برای جاوا اسکریپت که در مرورگر با استفاده از یک پنجره پاپ‌آپ برای رضایت کاربر اجرا می‌شود.

ماژول gapi.auth2 به طور خودکار توسط gapi.client.init() بارگذاری و استفاده می‌شود، و بنابراین پنهان است.

<!DOCTYPE html>
  <html>
    <head>
      <script src="https://apis.google.com/js/api.js"></script>
      <script>
        function start() {
          gapi.client.init({
            'apiKey': 'YOUR_API_KEY',
            'clientId': 'YOUR_CLIENT_ID',
            'scope': 'https://www.googleapis.com/auth/cloud-translation',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
          }).then(function() {
            // Execute an API request which is returned as a Promise.
            // The method name language.translations.list comes from the API discovery.
            return gapi.client.language.translations.list({
              q: 'hello world',
              source: 'en',
              target: 'de',
            });
          }).then(function(response) {
            console.log(response.result.data.translations[0].translatedText);
          }, function(reason) {
            console.log('Error: ' + reason.result.error.message);
          });
        };

        // Load the JavaScript client library and invoke start afterwards.
        gapi.load('client', start);
      </script>
    </head>
    <body>
      <div id="results"></div>
    </body>
  </html>

کتابخانه کلاینت JS

OAuth 2.0 برای برنامه‌های وب سمت کلاینت که در مرورگر اجرا می‌شوند و از یک پنجره‌ی پاپ‌آپ برای رضایت کاربر استفاده می‌کنند.

ماژول gapi.auth2 به صورت دستی بارگذاری می‌شود.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var GoogleAuth;
  var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
  function handleClientLoad() {
    // Load the API's client and auth2 modules.
    // Call the initClient function after the modules load.
    gapi.load('client:auth2', initClient);
  }

  function initClient() {
    // In practice, your app can retrieve one or more discovery documents.
    var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';

    // Initialize the gapi.client object, which app uses to make API requests.
    // Get API key and client ID from Google Cloud console.
    // 'scope' field specifies space-delimited list of access scopes.
    gapi.client.init({
        'apiKey': 'YOUR_API_KEY',
        'clientId': 'YOUR_CLIENT_ID',
        'discoveryDocs': [discoveryUrl],
        'scope': SCOPE
    }).then(function () {
      GoogleAuth = gapi.auth2.getAuthInstance();

      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);

      // Handle initial sign-in state. (Determine if user is already signed in.)
      var user = GoogleAuth.currentUser.get();
      setSigninStatus();

      // Call handleAuthClick function when user clicks on
      //      "Sign In/Authorize" button.
      $('#sign-in-or-out-button').click(function() {
        handleAuthClick();
      });
      $('#revoke-access-button').click(function() {
        revokeAccess();
      });
    });
  }

  function handleAuthClick() {
    if (GoogleAuth.isSignedIn.get()) {
      // User is authorized and has clicked "Sign out" button.
      GoogleAuth.signOut();
    } else {
      // User is not signed in. Start Google auth flow.
      GoogleAuth.signIn();
    }
  }

  function revokeAccess() {
    GoogleAuth.disconnect();
  }

  function setSigninStatus() {
    var user = GoogleAuth.currentUser.get();
    var isAuthorized = user.hasGrantedScopes(SCOPE);
    if (isAuthorized) {
      $('#sign-in-or-out-button').html('Sign out');
      $('#revoke-access-button').css('display', 'inline-block');
      $('#auth-status').html('You are currently signed in and have granted ' +
          'access to this app.');
    } else {
      $('#sign-in-or-out-button').html('Sign In/Authorize');
      $('#revoke-access-button').css('display', 'none');
      $('#auth-status').html('You have not authorized this app or you are ' +
          'signed out.');
    }
  }

  function updateSigninStatus() {
    setSigninStatus();
  }
</script>

<button id="sign-in-or-out-button"
        style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
        style="display: none; margin-left: 25px">Revoke access</button>

<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
        onload="this.onload=function(){};handleClientLoad()"
        onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>

نقاط پایانی OAuth 2.0

OAuth 2.0 برای برنامه‌های وب سمت کلاینت که در مرورگر اجرا می‌شوند و با استفاده از ریدایرکت به گوگل برای رضایت کاربر عمل می‌کنند.

این مثال فراخوانی‌های مستقیم به نقاط انتهایی OAuth 2.0 گوگل را از مرورگر کاربر نشان می‌دهد و از ماژول gapi.auth2 یا کتابخانه جاوا اسکریپت استفاده نمی‌کند.

<!DOCTYPE html>
<html><head></head><body>
<script>
  var YOUR_CLIENT_ID = 'REPLACE_THIS_VALUE';
  var YOUR_REDIRECT_URI = 'REPLACE_THIS_VALUE';
  var fragmentString = location.hash.substring(1);

  // Parse query string to see if page request is coming from OAuth 2.0 server.
  var params = {};
  var regex = /([^&=]+)=([^&]*)/g, m;
  while (m = regex.exec(fragmentString)) {
    params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
  }
  if (Object.keys(params).length > 0) {
    localStorage.setItem('oauth2-test-params', JSON.stringify(params) );
    if (params['state'] && params['state'] == 'try_sample_request') {
      trySampleRequest();
    }
  }

  // If there's an access token, try an API request.
  // Otherwise, start OAuth 2.0 flow.
  function trySampleRequest() {
    var params = JSON.parse(localStorage.getItem('oauth2-test-params'));
    if (params && params['access_token']) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET',
          'https://www.googleapis.com/drive/v3/about?fields=user&' +
          'access_token=' + params['access_token']);
      xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
          console.log(xhr.response);
        } else if (xhr.readyState === 4 && xhr.status === 401) {
          // Token invalid, so prompt for user permission.
          oauth2SignIn();
        }
      };
      xhr.send(null);
    } else {
      oauth2SignIn();
    }
  }

  /*

    *   Create form to request access token from Google's OAuth 2.0 server.
 */
function oauth2SignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';

    // Create element to open OAuth 2.0 endpoint in new window.
    var form = document.createElement('form');
    form.setAttribute('method', 'GET'); // Send as a GET request.
    form.setAttribute('action', oauth2Endpoint);

    // Parameters to pass to OAuth 2.0 endpoint.
    var params = {'client_id': YOUR_CLIENT_ID,
                  'redirect_uri': YOUR_REDIRECT_URI,
                  'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                  'state': 'try_sample_request',
                  'include_granted_scopes': 'true',
                  'response_type': 'token'};

    // Add form parameters as hidden input values.
    for (var p in params) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', p);
      input.setAttribute('value', params[p]);
      form.appendChild(input);
    }

    // Add form to page and submit it to open the OAuth 2.0 endpoint.
    document.body.appendChild(form);
    form.submit();
  }
</script>

<button onclick="trySampleRequest();">Try sample request</button>
</body></html>

راه جدید

فقط سیستم اطلاعات جغرافیایی

این مثال فقط کتابخانه جاوا اسکریپت سرویس هویت گوگل را با استفاده از مدل توکن و پنجره بازشو برای رضایت کاربر نشان می‌دهد. این مثال برای نشان دادن حداقل تعداد مراحل مورد نیاز برای پیکربندی یک کلاینت، درخواست و دریافت توکن دسترسی و فراخوانی یک API گوگل ارائه شده است.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      var access_token;

      function initClient() {
        client = google.accounts.oauth2.initTokenClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/contacts.readonly',
          callback: (tokenResponse) => {
            access_token = tokenResponse.access_token;
          },
        });
      }
      function getToken() {
        client.requestAccessToken();
      }
      function revokeToken() {
        google.accounts.oauth2.revoke(access_token, () => {console.log('access token revoked')});
      }
      function loadCalendar() {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'https://www.googleapis.com/calendar/v3/calendars/primary/events');
        xhr.setRequestHeader('Authorization', 'Bearer ' + access_token);
        xhr.send();
      }
    </script>
    <h1>Google Identity Services Authorization Token model</h1>
    <button onclick="getToken();">Get access token</button><br><br>
    <button onclick="loadCalendar();">Load Calendar</button><br><br>
    <button onclick="revokeToken();">Revoke token</button>
  </body>
</html>

GAPI ناهمگام/منتظر

این مثال نحوه‌ی افزودن کتابخانه‌ی سرویس هویت گوگل با استفاده از مدل توکن ، حذف ماژول gapi.auth2 و فراخوانی یک API با استفاده از کتابخانه‌ی کلاینت API گوگل برای جاوا اسکریپت را نشان می‌دهد.

Promises، async و await برای اعمال ترتیب بارگذاری کتابخانه و گرفتن و امتحان مجدد خطاهای مجوز استفاده می‌شوند. فراخوانی API فقط پس از در دسترس بودن یک توکن دسترسی معتبر انجام می‌شود.

از کاربران انتظار می‌رود در صورت عدم نمایش توکن دسترسی در اولین بارگذاری صفحه یا پس از انقضای توکن دسترسی، دکمه «نمایش تقویم» را فشار دهند.

<!DOCTYPE html>
<html>
<head>
    <title>GAPI and GIS Example</title>
    <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
    <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoad()"></script>
</head>
<body>
    <h1>GAPI Client with GIS Authorization</h1>
    <button id="authorizeBtn" style="visibility:hidden;">Authorize and Load Events</button>
    <button id="revokeBtn" style="visibility:hidden;">Revoke Access</button>
    <div id="content"></div>

    <script>
        const YOUR_CLIENT_ID = "YOUR_CLIENT_ID";
        const YOUR_API_KEY = 'YOUR_API_KEY';
        const CALENDAR_SCOPE = 'https://www.googleapis.com/auth/calendar.readonly';

        let tokenClient;
        let libsLoaded = 0;

        function gapiLoad() {
            gapi.load('client', initGapiClient);
        }

        async function initGapiClient() {
            try {
                await gapi.client.init({ apiKey: YOUR_API_KEY });
                await gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
                console.log('GAPI client initialized.');
                checkAllLoaded();
            } catch (err) {
                handleError('GAPI initialization failed:', err);
            }
        }

        function gisLoad() {
            try {
                tokenClient = google.accounts.oauth2.initTokenClient({
                    client_id: YOUR_CLIENT_ID,
                    scope: CALENDAR_SCOPE,
                    callback: '', // Will be set dynamically
                    error_callback: handleGisError,
                });
                console.log('GIS TokenClient initialized.');
                checkAllLoaded();
            } catch (err) {
                handleError('GIS initialization failed:', err);
            }
        }

        function checkAllLoaded() {
            libsLoaded++;
            if (libsLoaded === 2) {
                document.getElementById('authorizeBtn').style.visibility = 'visible';
                document.getElementById('revokeBtn').style.visibility = 'visible';
                document.getElementById('authorizeBtn').onclick = makeApiCall;
                document.getElementById('revokeBtn').onclick = revokeAccess;
                console.log('Ready to authorize.');
            }
        }

        function handleGisError(err) {
            console.error('GIS Error:', err);
            let message = 'An error occurred during authorization.';
            if (err && err.type === 'popup_failed_to_open') {
                message = 'Failed to open popup. Please disable popup blockers.';
            } else if (err && err.type === 'popup_closed') {
                message = 'Authorization popup was closed.';
            }
            document.getElementById('content').textContent = message;
        }

        function handleError(message, error) {
            console.error(message, error);
            document.getElementById('content').textContent = `${message} ${error.message || JSON.stringify(error)}`;
        }

        async function makeApiCall() {
            document.getElementById('content').textContent = 'Processing...';
            try {
                let token = gapi.client.getToken();
                if (!token || !token.access_token) {
                    console.log('No token, fetching one...');
                    await getToken();
                }

                console.log('Calling Calendar API...');
                const response = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
                displayEvents(response.result);
            } catch (err) {
                console.error('API call failed:', err);
                const errorInfo = err.result && err.result.error;
                if (errorInfo && (errorInfo.code === 401 || (errorInfo.code === 403 && errorInfo.status === "PERMISSION_DENIED"))) {
                    console.log('Auth error on API call, refreshing token...');
                    try {
                        await getToken({ prompt: 'consent' }); // Force refresh
                        const retryResponse = await gapi.client.calendar.events.list({ 'calendarId': 'primary' });
                        displayEvents(retryResponse.result);
                    } catch (refreshErr) {
                        handleError('Failed to refresh token or retry API call:', refreshErr);
                    }
                } else {
                    handleError('Error loading events:', err.result ? err.result.error : err);
                }
            }
        }

        async function getToken(options = { prompt: '' }) {
            return new Promise((resolve, reject) => {
                if (!tokenClient) return reject(new Error("GIS TokenClient not initialized."));
                tokenClient.callback = (tokenResponse) => {
                    if (tokenResponse.error) {
                        reject(new Error(`Token Error: ${tokenResponse.error} - ${tokenResponse.error_description}`));
                    } else {
                        console.log('Token acquired.');
                        resolve(tokenResponse);
                    }
                };
                tokenClient.requestAccessToken(options);
            });
        }

        function displayEvents(result) {
            const events = result.items;
            if (events && events.length > 0) {
                let eventList = '<h3>Upcoming Events:</h3><ul>' + events.map(event =>
                    `<li>${event.summary} (${event.start.dateTime || event.start.date})</li>`
                ).join('') + '</ul>';
                document.getElementById('content').innerHTML = eventList;
            } else {
                document.getElementById('content').textContent = 'No upcoming events found.';
            }
        }

        function revokeAccess() {
            const token = gapi.client.getToken();
            if (token && token.access_token) {
                google.accounts.oauth2.revoke(token.access_token, () => {
                    console.log('Access revoked.');
                    document.getElementById('content').textContent = 'Access has been revoked.';
                    gapi.client.setToken(null);
                });
            } else {
                document.getElementById('content').textContent = 'No token to revoke.';
            }
        }
    </script>
</body>
</html>

فراخوانی مجدد GAPI

این مثال نحوه‌ی افزودن کتابخانه‌ی سرویس هویت گوگل با استفاده از مدل توکن ، حذف ماژول gapi.auth2 و فراخوانی یک API با استفاده از کتابخانه‌ی کلاینت API گوگل برای جاوا اسکریپت را نشان می‌دهد.

متغیرها برای اعمال ترتیب بارگذاری کتابخانه استفاده می‌شوند. فراخوانی‌های GAPI از درون تابع فراخوانی پس از برگرداندن یک توکن دسترسی معتبر انجام می‌شوند.

انتظار می‌رود کاربران هنگام بارگذاری اولیه صفحه و همچنین هنگام به‌روزرسانی اطلاعات تقویم خود، دکمه نمایش تقویم را فشار دهند.

<!DOCTYPE html>
<html>
<head>
  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoad()"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisInit()"></script>
</head>
<body>
  <h1>GAPI with GIS callbacks</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>
  <script>
    let tokenClient;
    let gapiInited;
    let gisInited;

    document.getElementById("showEventsBtn").style.visibility="hidden";
    document.getElementById("revokeBtn").style.visibility="hidden";

    function checkBeforeStart() {
       if (gapiInited && gisInited){
          // Start only when both gapi and gis are initialized.
          document.getElementById("showEventsBtn").style.visibility="visible";
          document.getElementById("revokeBtn").style.visibility="visible";
       }
    }

    function gapiInit() {
      gapi.client.init({
        // NOTE: OAuth2 'scope' and 'client_id' parameters have moved to initTokenClient().
      })
      .then(function() {  // Load the Calendar API discovery document.
        gapi.client.load('https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest');
        gapiInited = true;
        checkBeforeStart();
      });
    }

    function gapiLoad() {
        gapi.load('client', gapiInit)
    }

    function gisInit() {
     tokenClient = google.accounts.oauth2.initTokenClient({
                client_id: 'YOUR_CLIENT_ID',
                scope: 'https://www.googleapis.com/auth/calendar.readonly',
                callback: '',  // defined at request time
            });
      gisInited = true;
      checkBeforeStart();
    }

    function showEvents() {

      tokenClient.callback = (resp) => {
        if (resp.error !== undefined) {
          throw(resp);
        }
        // GIS has automatically updated gapi.client with the newly issued access token.
        console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));

        gapi.client.calendar.events.list({ 'calendarId': 'primary' })
        .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
        .catch(err => console.log(err));

        document.getElementById("showEventsBtn").innerText = "Refresh Calendar";
      }

      // Conditionally ask users to select the Google Account they'd like to use,
      // and explicitly obtain their consent to fetch their Calendar.
      // NOTE: To request an access token a user gesture is necessary.
      if (gapi.client.getToken() === null) {
        // Prompt the user to select a Google Account and asked for consent to share their data
        // when establishing a new session.
        tokenClient.requestAccessToken({prompt: 'consent'});
      } else {
        // Skip display of account chooser and consent dialog for an existing session.
        tokenClient.requestAccessToken({prompt: ''});
      }
    }

    function revokeToken() {
      let cred = gapi.client.getToken();
      if (cred !== null) {
        google.accounts.oauth2.revoke(cred.access_token, () => {console.log('Revoked: ' + cred.access_token)});
        gapi.client.setToken('');
        document.getElementById("showEventsBtn").innerText = "Show Calendar";
      }
    }
  </script>
</body>
</html>

مثال‌هایی از جریان کد مجوز

رابط کاربری پاپ‌آپ کتابخانه سرویس هویت گوگل می‌تواند یا از یک تغییر مسیر URL برای بازگرداندن کد مجوز مستقیماً به نقطه پایانی توکن بک‌اند شما استفاده کند، یا از یک کنترل‌کننده فراخوانی جاوا اسکریپت که در مرورگر کاربر اجرا می‌شود و پاسخ را به پلتفرم شما پروکسی می‌کند. در هر صورت، پلتفرم بک‌اند شما جریان OAuth 2.0 را برای دریافت یک به‌روزرسانی معتبر و توکن دسترسی تکمیل خواهد کرد.

راه قدیمی

برنامه‌های وب سمت سرور

ورود به سیستم گوگل برای برنامه‌های سمت سرور که در پلتفرم بک‌اند اجرا می‌شوند و از طریق ریدایرکت به گوگل برای رضایت کاربر انجام می‌شود.

<!DOCTYPE html>
<html>
  <head>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
    <script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>
    <script>
      function start() {
        gapi.load('auth2', function() {
          auth2 = gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID',
            api_key: 'YOUR_API_KEY',
            discovery_docs: ['https://www.googleapis.com/discovery/v1/apis/translate/v2/rest'],
            // Scopes to request in addition to 'profile' and 'email'
            scope: 'https://www.googleapis.com/auth/cloud-translation',
          });
        });
      }
      function signInCallback(authResult) {
        if (authResult['code']) {
          console.log("sending AJAX request");
          // Send authorization code obtained from Google to backend platform
          $.ajax({
            type: 'POST',
            url: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
            // Always include an X-Requested-With header to protect against CSRF attacks.
            headers: {
              'X-Requested-With': 'XMLHttpRequest'
            },
            contentType: 'application/octet-stream; charset=utf-8',
            success: function(result) {
              console.log(result);
            },
            processData: false,
            data: authResult['code']
          });
        } else {
          console.log('error: failed to obtain authorization code')
        }
      }
    </script>
  </head>
  <body>
    <button id="signinButton">Sign In With Google</button>
    <script>
      $('#signinButton').click(function() {
        // Obtain an authorization code from Google
        auth2.grantOfflineAccess().then(signInCallback);
      });
    </script>
  </body>
</html>

HTTP/REST با استفاده از تغییر مسیر

استفاده از OAuth 2.0 برای برنامه‌های وب سرور برای ارسال کد مجوز از مرورگر کاربر به پلتفرم backend شما. رضایت کاربر با هدایت مرورگر کاربر به گوگل مدیریت می‌شود.

/\*
 \* Create form to request access token from Google's OAuth 2.0 server.
 \*/
function oauthSignIn() {
  // Google's OAuth 2.0 endpoint for requesting an access token
  var oauth2Endpoint = 'https://accounts.google.com/o/oauth2/v2/auth';
  // Create &lt;form> element to submit parameters to OAuth 2.0 endpoint.
  var form = document.createElement('form');
  form.setAttribute('method', 'GET'); // Send as a GET request.
  form.setAttribute('action', oauth2Endpoint);
  // Parameters to pass to OAuth 2.0 endpoint.
  var params = {'client\_id': 'YOUR_CLIENT_ID',
                'redirect\_uri': 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URL',
                'response\_type': 'token',
                'scope': 'https://www.googleapis.com/auth/drive.metadata.readonly',
                'include\_granted\_scopes': 'true',
                'state': 'pass-through value'};
  // Add form parameters as hidden input values.
  for (var p in params) {
    var input = document.createElement('input');
    input.setAttribute('type', 'hidden');
    input.setAttribute('name', p);
    input.setAttribute('value', params[p]);
    form.appendChild(input);
  }

  // Add form to page and submit it to open the OAuth 2.0 endpoint.
  document.body.appendChild(form);
  form.submit();
}

راه جدید

تجربه کاربری پاپ‌آپ GIS

این مثال فقط کتابخانه جاوا اسکریپت سرویس هویت گوگل را با استفاده از مدل کد مجوز، یک پنجره بازشو برای رضایت کاربر و کنترل‌کننده فراخوانی برای دریافت کد مجوز از گوگل نشان می‌دهد. این مثال برای نشان دادن حداقل تعداد مراحل مورد نیاز برای پیکربندی یک کلاینت، دریافت رضایت و ارسال کد مجوز به پلتفرم backend شما ارائه شده است.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly',
          ux_mode: 'popup',
          callback: (response) => {
            var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
            // Send auth code to your backend platform
            const xhr = new XMLHttpRequest();
            xhr.open('POST', code_receiver_uri, true);
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('code=' + response.code);
            // After receipt, the code is exchanged for an access token and
            // refresh token, and the platform then updates this web app
            // running in user's browser with the requested calendar info.
          },
        });
      }
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

تجربه کاربری تغییر مسیر GIS

مدل کد مجوز از حالت‌های پاپ‌آپ و ریدایرکت UX پشتیبانی می‌کند تا یک کد مجوز برای هر کاربر به نقطه پایانی میزبانی شده توسط پلتفرم شما ارسال شود. حالت ریدایرکت UX در اینجا نشان داده شده است:

<!DOCTYPE html>
<html>
  <head>
    <script src="https://accounts.google.com/gsi/client" onload="initClient()" async defer></script>
  </head>
  <body>
    <script>
      var client;
      function initClient() {
        client = google.accounts.oauth2.initCodeClient({
          client_id: 'YOUR_CLIENT_ID',
          scope: 'https://www.googleapis.com/auth/calendar.readonly \
                  https://www.googleapis.com/auth/photoslibrary.readonly',
          ux_mode: 'redirect',
          redirect_uri: 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI'
        });
      }
      // Request an access token
      function getAuthCode() {
        // Request authorization code and obtain user consent
        client.requestCode();
      }
    </script>
    <button onclick="getAuthCode();">Load Your Calendar</button>
  </body>
</html>

کتابخانه‌های جاوا اسکریپت

سرویس‌های هویت گوگل (Google Identity Services) یک کتابخانه جاوا اسکریپت واحد است که برای احراز هویت و مجوزدهی کاربر استفاده می‌شود و ویژگی‌ها و قابلیت‌های موجود در چندین کتابخانه و ماژول مختلف را ادغام و جایگزین می‌کند:

اقداماتی که باید هنگام مهاجرت به سرویس‌های هویت انجام دهید:

کتابخانه JS موجود کتابخانه جدید JS یادداشت‌ها
apis.google.com/js/api.js accounts.google.com/gsi/client کتابخانه جدید اضافه کنید و جریان ضمنی را دنبال کنید.
apis.google.com/js/client.js accounts.google.com/gsi/client کتابخانه جدید و جریان کد مجوز را اضافه کنید.

مرجع سریع کتابخانه

مقایسه شیء و متد بین کتابخانه قدیمی کلاینت جاوا اسکریپت Google Sign-In و کتابخانه جدید Google Identity Services و یادداشت‌هایی با اطلاعات و اقدامات اضافی که باید در طول مهاجرت انجام شود.

قدیمی جدید یادداشت‌ها
شیء GoogleAuth و متدهای مرتبط:
تابع ()GoogleAuth.attachClickHandler حذف
تابع ()GoogleAuth.currentUser.get حذف
تابع ()GoogleAuth.currentUser.listen حذف
GoogleAuth.disconnect() حساب‌های گوگل.oauth2.revoke قدیمی را با جدید جایگزین کنید. لغو مجوز ممکن است از طریق https://myaccount.google.com/permissions نیز انجام شود.
GoogleAuth.grantOfflineAccess() حذف کنید، جریان کد مجوز را دنبال کنید.
GoogleAuth.isSignedIn.get() حذف
GoogleAuth.isSignedIn.listen() حذف
ورود به سیستم ()GoogleAuth حذف
GoogleAuth.signOut() حذف
GoogleAuth.then() حذف
شیء GoogleUser و متدهای مرتبط:
تابع ()GoogleUser.disconnect شناسه.حساب‌های گوگل.لغو قدیمی را با جدید جایگزین کنید. لغو مجوز ممکن است از طریق https://myaccount.google.com/permissions نیز انجام شود.
تابع ()GoogleUser.getAuthResponse تابع requestCode() یا تابع requestAccessToken() تعویض قدیمی با جدید
تابع ()GoogleUser.getBasicProfile حذف کنید. به جای آن از شناسه توکن استفاده کنید، به مهاجرت از ورود به سیستم گوگل مراجعه کنید.
تابع ()GoogleUser.getGrantedScopes تابع hasGrantedAnyScope() تعویض قدیمی با جدید
تابع ()GoogleUser.getHostedDomain حذف
تابع ()GoogleUser.getId حذف
تابع ()googleuser.grantOfflineAccess حذف کنید، جریان کد مجوز را دنبال کنید.
تابع ()GoogleUser.grant حذف
تابع ()GoogleUser.hasGrantedScopes تابع hasGrantedAnyScope() تعویض قدیمی با جدید
تابع ()GoogleUser.isSignedIn حذف
تابع ()GoogleUser.reloadAuthResponse درخواست دسترسی توکن() قدیمی را حذف کنید، برای جایگزینی توکن دسترسی منقضی شده یا لغو شده، جدید را فراخوانی کنید.
شیء gapi.auth2 و متدهای مرتبط:
شیء gapi.auth2.AuthorizeConfig TokenClientConfig یا CodeClientConfig تعویض قدیمی با جدید
شیء gapi.auth2.AuthorizeResponse حذف
شیء gapi.auth2.AuthResponse حذف
gapi.auth2.authorize() تابع requestCode() یا تابع requestAccessToken() تعویض قدیمی با جدید
gapi.auth2.ClientConfig() TokenClientConfig یا CodeClientConfig تعویض قدیمی با جدید
gapi.auth2.getAuthInstance() حذف
gapi.auth2.init() initTokenClient() یا initCodeClient() تعویض قدیمی با جدید
شیء gapi.auth2.OfflineAccessOptions حذف
شیء gapi.auth2.SignInOptions حذف
شیء gapi.signin2 و متدهای مرتبط:
gapi.signin2.render() حذف. بارگذاری DOM HTML از عنصر g_id_signin یا فراخوانی JS به google.accounts.id.renderButton باعث ورود کاربر به حساب گوگل می‌شود.

مثال اعتبارنامه‌ها

مدارک تحصیلی موجود

کتابخانه پلتفرم ورود به سیستم گوگل ، کتابخانه کلاینت API گوگل برای جاوا اسکریپت ، یا فراخوانی‌های مستقیم به نقاط انتهایی Google OAuth 2.0، هم یک توکن دسترسی OAuth 2.0 و هم یک توکن شناسه اتصال OpenID را در یک پاسخ واحد برمی‌گردانند.

نمونه پاسخی که شامل access_token و id_token باشد:

  {
    "token_type": "Bearer",
    "access_token": "ya29.A0ARrdaM-SmArZaCIh68qXsZSzyeU-8mxhQERHrP2EXtxpUuZ-3oW8IW7a6D2J6lRnZrRj8S6-ZcIl5XVEqnqxq5fuMeDDH_6MZgQ5dgP7moY-yTiKR5kdPm-LkuPM-mOtUsylWPd1wpRmvw_AGOZ1UUCa6UD5Hg",
    "scope": "https://www.googleapis.com/auth/calendar.readonly",
    "login_hint": "AJDLj6I2d1RH77cgpe__DdEree1zxHjZJr4Q7yOisoumTZUmo5W2ZmVFHyAomUYzLkrluG-hqt4RnNxrPhArd5y6p8kzO0t8xIfMAe6yhztt6v2E-_Bb4Ec3GLFKikHSXNh5bI-gPrsI",
    "expires_in": 3599,
    "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjkzNDFhYmM0MDkyYjZmYzAzOGU0MDNjOTEwMjJkZDNlNDQ1MzliNTYiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJhY2NvdW50cy5nb29nbGUuY29tIiwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwiYXVkIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwic3ViIjoiMTE3NzI2NDMxNjUxOTQzNjk4NjAwIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXRfaGFzaCI6IkJBSW55TjN2MS1ZejNLQnJUMVo0ckEiLCJuYW1lIjoiQnJpYW4gRGF1Z2hlcnR5IiwicGljdHVyZSI6Imh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbS9hLS9BT2gxNEdnenAyTXNGRGZvbVdMX3VDemRYUWNzeVM3ZGtxTE5ybk90S0QzVXNRPXM5Ni1jIiwiZ2l2ZW5fbmFtZSI6IkJyaWFuIiwiZmFtaWx5X25hbWUiOiJEYXVnaGVydHkiLCJsb2NhbGUiOiJlbiIsImlhdCI6MTYzODk5MTYzOCwiZXhwIjoxNjM4OTk1MjM4LCJqdGkiOiI5YmRkZjE1YWFiNzE2ZDhjYmJmNDYwMmM1YWM3YzViN2VhMDQ5OTA5In0.K3EA-3Adw5HA7O8nJVCsX1HmGWxWzYk3P7ViVBb4H4BoT2-HIgxKlx1mi6jSxIUJGEekjw9MC-nL1B9Asgv1vXTMgoGaNna0UoEHYitySI23E5jaMkExkTSLtxI-ih2tJrA2ggfA9Ekj-JFiMc6MuJnwcfBTlsYWRcZOYVw3QpdTZ_VYfhUu-yERAElZCjaAyEXLtVQegRe-ymScra3r9S92TA33ylMb3WDTlfmDpWL0CDdDzby2asXYpl6GQ7SdSj64s49Yw6mdGELZn5WoJqG7Zr2KwIGXJuSxEo-wGbzxNK-mKAiABcFpYP4KHPEUgYyz3n9Vqn2Tfrgp-g65BQ",
    "session_state": {
      "extraQueryParams": {
        "authuser": "0"
      }
    },
    "first_issued_at": 1638991637982,
    "expires_at": 1638995236982,
    "idpId": "google"
  }

اعتبارنامه خدمات هویت گوگل

کتابخانه سرویس‌های هویت گوگل موارد زیر را برمی‌گرداند:

  • یا یک توکن دسترسی هنگام استفاده برای مجوز:

    {
      "access_token": "ya29.A0ARrdaM_LWSO-uckLj7IJVNSfnUityT0Xj-UCCrGxFQdxmLiWuAosnAKMVQ2Z0LLqeZdeJii3TgULp6hR_PJxnInBOl8UoUwWoqsrGQ7-swxgy97E8_hnzfhrOWyQBmH6zs0_sUCzwzhEr_FAVqf92sZZHphr0g",
      "token_type": "Bearer",
      "expires_in": 3599,
      "scope": "https://www.googleapis.com/auth/calendar.readonly"
    }
    
  • یا، یک توکن شناسایی هنگام استفاده برای احراز هویت:

    {
      "clientId": "538344653255-758c5h5isc45vgk27d8h8deabovpg6to.apps.googleusercontent.com",
      "credential": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImMxODkyZWI0OWQ3ZWY5YWRmOGIyZTE0YzA1Y2EwZDAzMjcxNGEyMzciLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJuYmYiOjE2MzkxNTcyNjQsImF1ZCI6IjUzODM0NDY1MzI1NS03NThjNWg1aXNjNDV2Z2syN2Q4aDhkZWFib3ZwZzZ0by5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjExNzcyNjQzMTY1MTk0MzY5ODYwMCIsIm5vbmNlIjoiZm9vYmFyIiwiaGQiOiJnb29nbGUuY29tIiwiZW1haWwiOiJkYWJyaWFuQGdvb2dsZS5jb20iLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiYXpwIjoiNTM4MzQ0NjUzMjU1LTc1OGM1aDVpc2M0NXZnazI3ZDhoOGRlYWJvdnBnNnRvLmFwcHMuZ29vZ2xldXNlcmNvbnRlbnQuY29tIiwibmFtZSI6IkJyaWFuIERhdWdoZXJ0eSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHZ3pwMk1zRkRmb21XTF91Q3pkWFFjc3lTN2RrcUxOcm5PdEtEM1VzUT1zOTYtYyIsImdpdmVuX25hbWUiOiJCcmlhbiIsImZhbWlseV9uYW1lIjoiRGF1Z2hlcnR5IiwiaWF0IjoxNjM5MTU3NTY0LCJleHAiOjE2MzkxNjExNjQsImp0aSI6IjRiOTVkYjAyZjU4NDczMmUxZGJkOTY2NWJiMWYzY2VhYzgyMmI0NjUifQ.Cr-AgMsLFeLurnqyGpw0hSomjOCU4S3cU669Hyi4VsbqnAV11zc_z73o6ahe9Nqc26kPVCNRGSqYrDZPfRyTnV6g1PIgc4Zvl-JBuy6O9HhClAK1HhMwh1FpgeYwXqrng1tifmuotuLQnZAiQJM73Gl-J_6s86Buo_1AIx5YAKCucYDUYYdXBIHLxrbALsA5W6pZCqqkMbqpTWteix-G5Q5T8LNsfqIu_uMBUGceqZWFJALhS9ieaDqoxhIqpx_89QAr1YlGu_UO6R6FYl0wDT-nzjyeF5tonSs3FHN0iNIiR3AMOHZu7KUwZaUdHg4eYkU-sQ01QNY_11keHROCRQ",
      "select_by": "user"
    }
    

پاسخ توکن نامعتبر است

نمونه پاسخ گوگل هنگام تلاش برای ارسال درخواست API با استفاده از توکن دسترسی منقضی شده، لغو شده یا نامعتبر:

هدرهای پاسخ HTTP

  www-authenticate: Bearer realm="https://accounts.google.com/", error="invalid_token"

بدنه پاسخ

  {
    "error": {
      "code": 401,
      "message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
      "errors": [
        {
          "message": "Invalid Credentials",
          "domain": "global",
          "reason": "authError",
          "location": "Authorization",
          "locationType": "header"
        }
      ],
      "status": "UNAUTHENTICATED"
    }
  }