نقل البيانات إلى Google Identity Services

نظرة عامة

للحصول على رمز وصول لكل مستخدم للاتصال بواجهات برمجة تطبيقات Google، تقدّم Google عدة مكتبات JavaScript:

يوفّر هذا الدليل تعليمات لنقل البيانات من هذه المكتبات إلى مكتبة "خدمات هوية Google".

من خلال اتّباع هذا الدليل، يمكنك إجراء ما يلي:

  • استبدِل مكتبة Platform Library المتوقّفة نهائيًا بمكتبة Identity Services،
  • في حال استخدام مكتبة برامج واجهة برمجة التطبيقات، عليك إزالة وحدة gapi.auth2 التي تم إيقافها نهائيًا، وطرقها وعناصرها، واستبدالها بعناصر مكافئة في Identity Services.

للحصول على وصف لما تم تغييره في مكتبة JavaScript لخدمات الهوية، يمكنك الاطّلاع على النظرة العامة وكيفية عمل تفويض المستخدم لمراجعة المصطلحات والمفاهيم الرئيسية.

إذا كنت تبحث عن مصادقة لتسجيل المستخدمين وتسجيل دخولهم، اطّلِع على مقالة نقل البيانات من ميزة "تسجيل الدخول باستخدام حساب Google" بدلاً من ذلك.

تحديد مسار المصادقة

هناك عمليتان محتملتان لتفويض المستخدم: التفويض الضمني ورمز التفويض.

راجِع تطبيق الويب لتحديد نوع عملية التفويض التي يتم استخدامها حاليًا.

مؤشرات على أنّ تطبيق الويب يستخدم المسار التلقائي:

علامات تدل على أنّ تطبيق الويب يستخدم مسار رمز التفويض:

في بعض الحالات، قد تتوافق قاعدة الرموز مع كلا المسارَين.

اختيار عملية التفويض

قبل البدء في الترحيل، تحتاج إلى تحديد ما إذا كانت الاستمرار في التدفق الحالي أو اعتماد تدفق مختلف يلبي احتياجاتك على أفضل وجه.

راجِع مقالة اختيار مسار التفويض لفهم الاختلافات الرئيسية والتنازلات بين المسارين.

في معظم الحالات، يُنصَح باتّباع مسار رمز التفويض لأنّه يوفّر أعلى مستوى من الأمان للمستخدم. يتيح تنفيذ هذه العملية أيضًا ل منصتك إضافة وظائف جديدة بلا إنترنت بسهولة أكبر، مثل جلب آخر الأخبار لإعلام المستخدمين بالتغييرات البارزة في تقويمهم وصورهم واشتراكاتهم وغيرها.

اختَر مسار التفويض باستخدام أدوات الاختيار أدناه.

التدفق الضمني

الحصول على رمز دخول للاستخدام داخل المتصفح أثناء تواجد المستخدم.

تعرِض أمثلة على المسار الضمني تطبيقات الويب قبل نقلها إلى Identity Services وبعد نقلها.

مسار رمز التفويض

يتم تسليم رمز تفويض لكل مستخدم من Google إلى نظامك الأساسي في الخلفية، حيث يتم استبداله بعد ذلك برمز الدخول ورمز التحديث المميز.

تعرِض أمثلة على عملية رمز التفويض تطبيقات الويب قبل النقل إلى "خدمات إدارة الهوية" وبعده.

اتّبِع التعليمات المُدرَجة بخط عريض في هذا الدليل لإضافة أو إزالة أو تعديل أو استبدال الوظيفة الحالية.

التغييرات في تطبيق الويب المُدمَج في المتصفّح

يراجع هذا القسم التغييرات التي ستُجريها على تطبيق الويب المُشغَّل داخل المتصفّح عند نقله إلى مكتبة JavaScript في Google Identity Services.

تحديد الرمز البرمجي المتأثر والاختبار

يمكن أن يساعد ملف تعريف ارتباط تصحيح الأخطاء في تحديد مكان الرمز البرمجي المتأثّر واختبار السلوك بعد إيقاف الميزة نهائيًا.

في التطبيقات الكبيرة أو المعقّدة، قد يكون من الصعب العثور على كل الرموز البرمجية المتأثّرة بمحاولة إيقاف وحدة gapi.auth2 نهائيًا. لتسجيل الاستخدام الحالي للوظيفة التي سيتم إيقافها نهائيًا قريبًا في وحدة التحكّم، اضبط قيمة ملف تعريف الارتباط G_AUTH2_MIGRATION على informational. يمكنك اختياريًا إضافة علامة نقطتَين متبوعة بقيمة مفتاح لتسجيل الدخول أيضًا إلى مساحة تخزين الجلسة. بعد تسجيل الدخول واستلام مراجعة بيانات الاعتماد أو إرسال السجلات التي تم جمعها إلى إحدى الخلفيات لتحليلها لاحقًا. على سبيل المثال، يحفظ informational:showauth2use المصدر وعنوان URL في مفتاح تخزين الجلسة الذي يحمل الاسم showauth2use.

للتأكّد من سلوك التطبيق عند إيقاف تحميل وحدة gapi.auth2، اضبط قيمة ملف تعريف الارتباط G_AUTH2_MIGRATION على enforced. يتيح ذلك اختبار السلوك بعد الإيقاف النهائي قبل تاريخ التنفيذ.

قيم ملفّ تعريف الارتباط G_AUTH2_MIGRATION المحتمَلة:

  • enforced لا تحمِّل وحدة gapi.auth2.
  • informational تسجيل استخدام الوظائف المتوقّفة نهائيًا في وحدة تحكّم JavaScript سجِّل أيضًا في مساحة تخزين الجلسة عند ضبط اسم مفتاح اختياري: informational:key-name.

للحدّ من تأثير المستخدم، ننصحك أولاً بإعداد ملف تعريف الارتباط هذا محليًا أثناء التطوير والاختبار، قبل استخدامه في بيئات الإنتاج.

المكتبات والوحدات

تدير وحدة gapi.auth2 مصادقة المستخدمين لتسجيل الدخول والمسار التلقائي للتفويض، ويمكنك استبدال هذه الوحدة التي تم إيقافها نهائيًا وعناصرها وطرقها بمكتبة Google 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 لتطبيقات JavaScript، والاستفادة من إنشاءها التلقائي لطرق JavaScript القابلة للاستدعاء من مستند الاكتشاف، وتجميع طلبات بيانات متعددة من واجهة برمجة التطبيقات، ووظائف إدارة CORS.

بسكويت

لا يتطلّب تفويض المستخدم استخدام ملفات تعريف الارتباط.

اطّلِع على مقالة نقل البيانات من ميزة "تسجيل الدخول باستخدام حساب Google" لمعرفة تفاصيل عن كيفية استخدام ملفات تعريف الارتباط في عملية مصادقة المستخدمين، وكيفية استخدام Google لملفات تعريف الارتباط لمعرفة كيفية استخدام ملفات تعريف الارتباط في منتجات Google وخدماتها الأخرى.

بيانات الاعتماد

تفصل "خدمات هوية Google" مصادقة المستخدم وتفويضه في عمليتين منفصلتين، وتكون بيانات اعتماد المستخدم منفصلة: يتم إرجاع رمز المعرّف المستخدم لتحديد هوية المستخدم بشكل منفصل عن رمز الدخول المستخدم في الترخيص.

للاطّلاع على هذه التغييرات، يمكنك الاطّلاع على أمثلة على بيانات الاعتماد.

التدفّق الضمني

افصل مصادقة المستخدم وتفويضه عن طريق إزالة معالجة ملف المستخدم الشخصي من تدفقات التفويض.

أزِل مراجع JavaScript الخاصة بخدمة "تسجيل الدخول باستخدام حساب Google" التالية:

الطُرق

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

مسار رمز التفويض

تفصل "خدمات الهوية" بيانات الاعتماد داخل المتصفح إلى رمز مميز للمعرّف ورمز مميز للوصول. لا ينطبق هذا التغيير على بيانات الاعتماد التي يتم الحصول عليها من خلال طلبات مباشرة إلى نقاط نهاية Google OAuth 2.0 من منصّة الخلفية أو من خلال مكتبات تتمّ إدارتها على خادم آمن على منصّتك، مثل عميل Google APIs Node.js.

حالة الجلسة

في السابق، كانت ميزة "تسجيل الدخول باستخدام حساب Google" تساعدك في إدارة حالة تسجيل دخول المستخدم باستخدام:

تكون أنت المسؤول عن إدارة حالة تسجيل الدخول وجلسات المستخدمين على تطبيق الويب.

أزِل مراجع JavaScript الخاصة بخدمة "تسجيل الدخول باستخدام حساب Google" التالية:

الكائنات:

  • 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()

إعداد بيانات العميل

عدِّل تطبيق الويب لإعداد عميل رمز مميّز لمسار الرمز المميّز للسماح الضمني أو الصريح.

أزِل مراجع JavaScript الخاصة بخدمة "تسجيل الدخول باستخدام حساب Google" التالية:

العناصر:

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

الطرق:

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

التدفق الضمني

أضِف عنصر TokenClientConfig وطلب initTokenClient() ل ضبط إعدادات تطبيق الويب، باتّباع المثال في تهيئة رمز مميّز لعملاء.

استبدال مراجع عميل JavaScript لتسجيل الدخول بحساب Google بـ خدمات الهوية من Google:

العناصر:

  • 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".

عند التبديل من مسار الموافقة الضمنية إلى مسار رمز التفويض:

إزالة مراجع عميل JavaScript لتسجيل الدخول إلى Google

العناصر:

  • gapi.auth2.AuthorizeConfig

الطُرق:

  • gapi.auth2.init()

المَعلمات:

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

طلب الرمز المميّز

تؤدي إيماءة المستخدم، مثل النقر على زر، إلى إنشاء طلب يؤدي إلى عرض رمز تدفق ملف تعريف اعتماد مباشر في متصفّح المستخدم، أو إلى منصّة الخلفية بعد تبادل رمز التفويض لكل مستخدم للحصول على رمز تدفق ملف تعريف اعتماد ورمز إعادة التنشيط.

التدفّق الضمني

يمكن الحصول على رموز الوصول واستخدامها في المتصفّح عندما يكون المستخدم مسجّلاً الدخول ولديه جلسة نشطة مع Google. في الوضع التلقائي، يجب أن يُجري المستخدم إشارة لطلب الحصول على رمز دخول، حتى إذا سبق أن تم تقديم طلب.

استبدِل مراجع عملاء Google Sign-In JavaScript: باستخدام Google Identity Services:

الطُرق:

  • gapi.auth2.authorize() مع TokenClient.requestAccessToken()
  • GoogleUser.reloadAuthResponse() مع TokenClient.requestAccessToken()

أضِف رابطًا أو زرًا للاتصال بـ requestAccessToken() لبدء مسار تجربة المستخدِم المنبثق لطلب رمز دخول، أو للحصول على رمز دخول جديد عند انتهاء صلاحية رمز المرور الحالي.

عدِّل قاعدة بياناتك البرمجية إلى:

  • شغِّل مسار رمز OAuth 2.0 المميّز باستخدام requestAccessToken().
  • إتاحة التفويض المتزايد باستخدام requestAccessToken و OverridableTokenClientConfig لفصل طلب واحد لعدة نطاقات إلى طلبات متعددة أصغر
  • يمكنك طلب رمز مميّز جديد عند انتهاء صلاحية الرمز المميّز الحالي أو إبطاله.

قد يتطلّب العمل مع نطاقات متعددة إجراء تغييرات هيكلية على قاعدة بياناتك لطلب الوصول إلى النطاقات عند الحاجة فقط بدلاً من طلب الوصول إليها كلها في آنٍ واحد. ويُعرف هذا باسم التفويض المتزايد. يجب أن يحتوي كل طلب على أقل عدد ممكن من النطاقات، ومن الأفضل أن يحتوي على نطاق واحد. اطّلِع على كيفية التعامل مع موافقة المستخدم للتعرّف على مزيد من المعلومات حول كيفية تحديث تطبيقك للحصول على موافقة متصاعدة.

عند انتهاء صلاحية رمز مميّز للوصول، تحصل وحدة gapi.auth2 تلقائيًا على رمز مميّز جديد وصالح للوصول إلى تطبيق الويب. ولتحسين أمان المستخدم، لا تتوافق عملية إعادة تحميل الرمز المميّز التلقائية هذه مع مكتبة خدمات هوية Google. يجب تحديث تطبيق الويب لاكتشاف رمز الدخول منتهي الصلاحية وطلب رمز جديد. راجِع قسم "معالجة الرمز المميّز" أدناه لمعرفة المزيد.

مسار رمز التفويض

أضِف رابطًا أو زرًا للاتصال بـ requestCode() من أجل طلب رمز تفويض من Google. للحصول على مثال، يُرجى الاطّلاع على مسار رموز OAuth 2.0 المشغِّل.

اطّلِع على قسم "معالجة الرمز المميّز" أدناه لمعرفة المزيد من المعلومات عن كيفية الردّ على رمز مميّز للوصول منتهي الصلاحية أو مُلغى.

معالجة الرموز المميّزة

أضِف معالجة الأخطاء لرصد عمليات طلب بيانات من Google API التي تنتهي بالفشل عند استخدام رمز مميز للوصول منتهي الصلاحية أو مُلغى، وطلب رمز مميز جديد صالح للوصول.

تعرض Google APIs رمز حالة HTTP‏ 401 Unauthorized ورسالة الخطأ invalid_token عند استخدام رمز مميّز للوصول منتهي الصلاحية أو مُلغى. للحصول على مثال، يُرجى الاطّلاع على ردّ غير صالح على الرمز المميّز.

الرموز المميّزة المنتهية الصلاحية

رموز الدخول قصيرة الأجل، وغالبًا ما تكون صالحة لبضع دقائق فقط.

إبطال الرمز المميّز

يجوز لصاحب حساب Google إبطال الموافقة التي تم منحها سابقًا في أي وقت. يؤدي ذلك إلى إبطال رموز الدخول والرموز المميزة لإعادة التحميل الحالية. يمكن أن يتم تفعيل عملية الإبطال من منصتك باستخدام revoke() أو من خلال حساب Google.

استبدال مراجع عميل JavaScript لتسجيل الدخول بحساب Google: باستخدام خدمات هوية Google:

الطُرق:

  • getAuthInstance().disconnect() مع google.accounts.oauth2.revoke()
  • GoogleUser.disconnect() مع google.accounts.oauth2.revoke()

يمكنك الاتصال بالرقم revoke عندما يحذف مستخدم حسابه على منصتك أو إذا أراد إزالة موافقته على مشاركة البيانات مع تطبيقك.

يعرض Google مربّع إفادة موافقة للمستخدم عندما يطلب تطبيق الويب أو النظام الأساسي في الخلفية رمز دخول. اطّلِع على أمثلة على مربّعات حوار طلب الموافقة التي تعرِضها Google للمستخدمين.

قبل إصدار رمز دخول لتطبيقك، يجب أن تكون جلسة Google حالية ونشطة لطلب موافقة المستخدم وتسجيل النتيجة. قد يُطلَب من المستخدم تسجيل الدخول إلى حساب Google إذا لم يتم إنشاء جلسة حالية.

تسجيل دخول المستخدم

قد يكون المستخدمون مسجّلين الدخول إلى حساب Google في علامة تبويب متصفّح منفصلة، أو من خلال متصفّح أو نظام تشغيل بشكلٍ أصلي. ننصحك بإضافة ميزة تسجيل الدخول باستخدام حساب Google إلى موقعك الإلكتروني لإنشاء جلسة نشطة بين حساب Google والمتصفّح عندما يفتح المستخدم تطبيقك لأول مرة. ويقدّم لك إجراء ذلك الفوائد التالية:

  • تقليل عدد المرات التي يجب أن يسجّل فيها المستخدم الدخول، حيث يؤدي طلب رمز عبور للوصول إلى بدء عملية تسجيل الدخول إلى حساب Google إذا لم تكن هناك جلسة نشطة حالية
  • استخدِم مباشرةً حقل email مستند الاعتماد الخاص برمز تعريف JWT باعتباره قيمة المَعلمة login_hint في كائنَي CodeClientConfig أو TokenClientConfig. ويُعدّ هذا مفيدًا بشكل خاص إذا كانت منصّتك لا تحافظ على نظام لإدارة حسابات المستخدمين.
  • يمكنك البحث عن حساب Google وربطه بحساب مستخدم حالي على منصتك، ما يساعد في الحدّ من تكرار الحسابات على منصتك.
  • عند إنشاء حساب جديد على الجهاز، يمكن فصل مربّعات حوار عملية الاشتراك ومسارات الاشتراك بوضوح عن مربّعات حوار مصادقة المستخدم ومسارات المصادقة، ما يقلل من عدد الخطوات المطلوبة ويحسن معدّل الانسحاب.

بعد تسجيل الدخول وقبل إصدار رمز دخول، على المستخدمين تقديم موافقة لتطبيقك على النطاقات المطلوبة.

بعد الموافقة، يتم عرض رمز مميّز للوصول مع قائمة بالنطاقات التي وافق عليها أو رفضها المستخدم.

تسمح الأذونات الدقيقة للمستخدمين بالموافقة على نطاقات فردية أو رفضها. عند طلب الوصول إلى نطاقات متعددة، يتم منح كل نطاق أو رفضه بغض النظر عن النطاقات الأخرى. استنادًا إلى اختيار المستخدم، يُفعِّل تطبيقك بشكل انتقائي الميزات والوظائف التي تعتمد على نطاق فردي.

التدفق الضمني

استبدال مراجع عميل JavaScript لتسجيل الدخول بحساب Google بـ خدمات الهوية من Google:

العناصر:

  • gapi.auth2.AuthorizeResponse مع TokenClient.TokenResponse
  • gapi.auth2.AuthResponse مع TokenClient.TokenResponse

الطرق:

  • GoogleUser.hasGrantedScopes() مع google.accounts.oauth2.hasGrantedAllScopes()
  • GoogleUser.getGrantedScopes() مع google.accounts.oauth2.hasGrantedAllScopes()

أزِل مراجع JavaScript الخاصة بخدمة "تسجيل الدخول باستخدام حساب Google":

الطرق:

  • GoogleUser.getAuthResponse()

عدِّل تطبيق الويب باستخدام hasGrantedAllScopes() و hasGrantedAnyScope() باتّباع مثال الأذونات الدقيقة هذا.

مسار رمز التفويض

يمكنك تعديل أو إضافة نقطة نهاية رمز التفويض إلى منصة الخلفية من خلال اتّباع التعليمات الواردة في التعامل مع رمز التفويض.

عدِّل منصتك لاتّباع الخطوات الموضّحة في دليل استخدام نموذج الرمز من أجل التحقّق من صحة الطلب والحصول على رمز الدخول وإعادة تحميل الرمز.

عدِّل منصتك لتفعيل الميزات والوظائف أو إيقافها بشكل انتقائي استنادًا إلى النطاقات الفردية التي وافق عليها المستخدم من خلال اتّباع تعليمات التفويض المتزايد وفحص نطاقات الوصول التي منحها المستخدم.

أمثلة على التدفّق الضمني

الطريقة القديمة

مكتبة عملاء GAPI

مثال على مكتبة برامج Google API لواجهة برمجة التطبيقات JavaScript قيد التشغيل في المتصفّح باستخدام مربّع حوار منبثق للحصول على موافقة المستخدِم

يتم تحميل وحدة 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>

مكتبة عملاء JavaScript

بروتوكول 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 API 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 لتطبيقات الويب من جهة العميل التي تعمل في المتصفّح باستخدام عمليات إعادة التوجيه إلى Google للحصول على موافقة المستخدم

يعرض هذا المثال طلبات مباشرة إلى نقاط نهاية بروتوكول OAuth 2.0 من Google من متصفح العميل ولا يستخدم وحدة gapi.auth2 أو مكتبة JavaScript.

<!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>

الطريقة الجديدة

أنظمة المعلومات الجغرافية فقط

لا يعرض هذا المثال سوى مكتبة JavaScript في Google Identity Service باستخدام نموذج الرمز المميّز ومربّع الحوار المنبثق للحصول على موافقة المستخدم. ويتم توفيره لتوضيح الحد الأدنى لعدد الخطوات المطلوبة لضبط العميل، وطلب الحصول على رمز مميّز للوصول، والاتّصال بواجهة برمجة تطبيقات Google.

<!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 غير متزامنة/في انتظار المعالجة

يوضّح هذا المثال كيفية إضافة مكتبة Google Identity Service باستخدام نموذج الرمز المميّز، وإزالة وحدة gapi.auth2، واستدعاء واجهة برمجة تطبيقات باستخدام مكتبة Google API Client Library لبرامج JavaScript.

تُستخدَم وعدَي async وawait لفرض ترتيب تحميل المكتبة وللعثور على أخطاء التفويض وإعادة المحاولة. لا يتم إجراء استدعاء واجهة برمجة التطبيقات إلا بعد توفر رمز دخول صالح.

من المتوقّع أن يضغط المستخدمون على الزر "عرض التقويم" عند عدم ظهور رمز الدخول عند تحميل الصفحة لأول مرة، أو في وقت لاحق بعد انتهاء صلاحية رمز الدخول.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <h1>GAPI with GIS async/await</h1>
  <button id="showEventsBtn" onclick="showEvents();">Show Calendar</button><br><br>
  <button id="revokeBtn" onclick="revokeToken();">Revoke access token</button>

  <script>

    const gapiLoadPromise = new Promise((resolve, reject) => {
      gapiLoadOkay = resolve;
      gapiLoadFail = reject;
    });
    const gisLoadPromise = new Promise((resolve, reject) => {
      gisLoadOkay = resolve;
      gisLoadFail = reject;
    });

    var tokenClient;

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

      // First, load and initialize the gapi.client
      await gapiLoadPromise;
      await new Promise((resolve, reject) => {
        // NOTE: the 'auth2' module is no longer loaded.
        gapi.load('client', {callback: resolve, onerror: reject});
      });
      await 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');
      });

      // Now load the GIS client
      await gisLoadPromise;
      await new Promise((resolve, reject) => {
        try {
          tokenClient = google.accounts.oauth2.initTokenClient({
              client_id: 'YOUR_CLIENT_ID',
              scope: 'https://www.googleapis.com/auth/calendar.readonly',
              prompt: 'consent',
              callback: '',  // defined at request time in await/promise scope.
          });
          resolve();
        } catch (err) {
          reject(err);
        }
      });

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

    async function getToken(err) {

      if (err.result.error.code == 401 || (err.result.error.code == 403) &&
          (err.result.error.status == "PERMISSION_DENIED")) {

        // The access token is missing, invalid, or expired, prompt for user consent to obtain one.
        await new Promise((resolve, reject) => {
          try {
            // Settle this promise in the response callback for requestAccessToken()
            tokenClient.callback = (resp) => {
              if (resp.error !== undefined) {
                reject(resp);
              }
              // GIS has automatically updated gapi.client with the newly issued access token.
              console.log('gapi.client access token: ' + JSON.stringify(gapi.client.getToken()));
              resolve(resp);
            };
            tokenClient.requestAccessToken();
          } catch (err) {
            console.log(err)
          }
        });
      } else {
        // Errors unrelated to authorization: server errors, exceeding quota, bad requests, and so on.
        throw new Error(err);
      }
    }

    function showEvents() {

      // Try to fetch a list of Calendar events. If a valid access token is needed,
      // prompt to obtain one and then retry the original request.
      gapi.client.calendar.events.list({ 'calendarId': 'primary' })
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => getToken(err))  // for authorization errors obtain an access token
      .then(retry => gapi.client.calendar.events.list({ 'calendarId': 'primary' }))
      .then(calendarAPIResponse => console.log(JSON.stringify(calendarAPIResponse)))
      .catch(err  => console.log(err)); // cancelled by user, timeout, etc.
    }

    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('');
      }
    }

  </script>

  <script async defer src="https://apis.google.com/js/api.js" onload="gapiLoadOkay()" onerror="gapiLoadFail(event)"></script>
  <script async defer src="https://accounts.google.com/gsi/client" onload="gisLoadOkay()" onerror="gisLoadFail(event)"></script>

</body>
</html>

معاودة الاتصال بواجهة برمجة التطبيقات من Google

يوضّح هذا المثال كيفية إضافة مكتبة Google Identity Service باستخدام نموذج الرمز المميّز، وإزالة وحدة gapi.auth2، واستدعاء واجهة برمجة تطبيقات باستخدام مكتبة Google API Client Library لبرامج JavaScript.

تُستخدَم المتغيّرات لفرض ترتيب تحميل المكتبة. يتم إجراء استدعاءات GAPI من داخل عملية الاستدعاء بعد إرجاع رمز دخول صالح.

من المتوقع أن يضغط المستخدمون على زر "إظهار التقويم" عند تحميل الصفحة لأول مرة، ومرة أخرى عندما يريدون إعادة تحميل معلومات "تقويم Google".

<!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>

أمثلة على مسار رمز التفويض

يمكن لتجربة المستخدم في النافذة المنبثقة لمكتبة "خدمة Google Identity" إما استخدام إعادة توجيه عنوان URL لعرض رمز التفويض مباشرةً إلى نقطة نهاية الرمز المميّز للخلفية، أو معالِج استدعاء JavaScript الذي يتم تشغيله في متصفّح المستخدم والذي يعمل على إنشاء خادم وكيل للاستجابة للنظام الأساسي. وفي كلتا الحالتَين، ستُكمِل منصة الخلفية عملية OAuth 2.0 للحصول على رمزَي إعادة تحميل ودخول صالحَين.

الطريقة القديمة

تطبيقات الويب من جهة الخادم

تسجيل الدخول باستخدام حساب Google للتطبيقات من جهة الخادم التي تعمل على منصة الخلفية باستخدام إعادة توجيه إلى Google للحصول على موافقة المستخدم

<!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 لتطبيقات خادم الويب لإرسال رمز التفويض من متصفّح المستخدم إلى منصّة الخلفية يتم التعامل مع موافقة المستخدم من خلال إعادة توجيه متصفح المستخدم إلى Google.

/\*
 \* 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();
}

الطريقة الجديدة

تجربة المستخدم في النافذة المنبثقة لنظام المعلومات الجغرافية

لا يعرض هذا المثال سوى مكتبة JavaScript لخدمة Google Identity Service باستخدام نموذج رمز التفويض، وهو عبارة عن مربّع حوار منبثق لموافقة المستخدم ومعالج callback لتلقّي رمز التفويض من Google. يتم تقديمه لشرح الحد الأدنى لعدد الخطوات المطلوبة لضبط العميل والحصول على الموافقة وإرسال رمز التفويض إلى منصّة الخلفي ة.

<!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>

تجربة المستخدم في إعادة التوجيه باستخدام نظام المعلومات الجغرافية

يتوافق نموذج رمز التفويض مع النافذة المنبثقة وأوضاع تجربة المستخدم لإعادة التوجيه لإرسال رمز تفويض لكل مستخدم إلى نقطة النهاية التي تستضيفها المنصة. يظهر وضع تجربة المستخدم لإعادة التوجيه هنا:

<!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>

مكتبات JavaScript

Google Identity Services هي مكتبة JavaScript واحدة تُستخدَم في مصادقة المستخدمين وتفويضهم، وهي تدمج الميزات ويحلّ محلّها الوظائف المتوفّرة في مكتبات ووحدات متعددة مختلفة:

الإجراءات التي يجب اتّخاذها عند نقل البيانات إلى Identity Services:

مكتبة JS الحالية مكتبة JavaScript جديدة ملاحظات
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 JavaScript client ومكتبة الجديدة Google Identity Services وملاحظات تتضمّن معلومات إضافية وإجراءات يجب اتّخاذها أثناء نقل البيانات

الإصدار القديم جديد ملاحظات
عنصر GoogleAuth والطُرق المرتبطة به:
GoogleAuth.attachClickHandler() إزالة
GoogleAuth.currentUser.get() إزالة
GoogleAuth.currentUser.listen() إزالة
GoogleAuth.disconnect() google.accounts.oauth2.revoke استبدِل المحتوى القديم بمحتوى جديد. يمكن أيضًا إلغاء الأذونات من https://myaccount.google.com/permissions.
GoogleAuth.grantOfflineAccess() عليك إزالته واتّباع مسار رمز التفويض.
GoogleAuth.isSignedIn.get() إزالة
GoogleAuth.isSignedIn.listen() إزالة
GoogleAuth.signIn() إزالة
GoogleAuth.signOut() إزالة
GoogleAuth.then() إزالة
عنصر GoogleUser والطُرق المرتبطة به:
GoogleUser.disconnect() google.accounts.id.revoke استبدِل المحتوى القديم بمحتوى جديد. قد يتم إبطال الأذونات أيضًا من خلال الرابط https://myaccount.google.com/permissions
GoogleUser.getAuthResponse() requestCode() or requestAccessToken() استبدال المحتوى القديم بمحتوى جديد
GoogleUser.getBasicProfile() إزالة. يمكنك استخدام الرمز المميّز لرقم التعريف بدلاً من ذلك، ويمكنك الاطّلاع على المقالة نقل البيانات من صفحة "تسجيل الدخول بحساب Google".
GoogleUser.getGrantedScopes() hasGrantedAnyScope() استبدال المحتوى القديم بمحتوى جديد
GoogleUser.getHostedDomain() إزالة
GoogleUser.getId() إزالة
GoogleUser.grantOfflineAccess() عليك إزالته واتّباع مسار رمز التفويض.
GoogleUser.grant() إزالة
GoogleUser.hasGrantedScopes() hasGrantedAnyScope() استبدال القديم بجديد
GoogleUser.isSignedIn() إزالة
GoogleUser.reloadAuthResponse() requestAccessToken() أزِل الرمز القديم واطلب رمزًا جديدًا لاستبدال رمز الوصول المنتهي الصلاحية أو المُلغى.
عنصر gapi.auth2 والطُرق المرتبطة به:
عنصر gapi.auth2.AuthorizeConfig TokenClientConfig أو CodeClientConfig استبدال المحتوى القديم بمحتوى جديد
عنصر gapi.auth2.AuthorizeResponse إزالة
عنصر gapi.auth2.AuthResponse إزالة
gapi.auth2.authorize() requestCode() or requestAccessToken() استبدال المحتوى القديم بمحتوى جديد
gapi.auth2.ClientConfig() TokenClientConfig أو CodeClientConfig استبدال المحتوى القديم بمحتوى جديد
gapi.auth2.getAuthInstance() إزالة
gapi.auth2.init() initTokenClient() or initCodeClient() استبدال القديم بجديد
عنصر gapi.auth2.OfflineAccessOptions إزالة
عنصر gapi.auth2.SignInOptions إزالة
الكائن gapi.signin2 والطرق المرتبطة به:
gapi.signin2.render() إزالة. يؤدي تحميل HTML DOM للعنصر g_id_signin أو طلب JS إلى google.accounts.id.renderButton إلى تسجيل دخول المستخدم إلى حساب Google.

أمثلة على بيانات الاعتماد

بيانات الاعتماد الحالية

تُعرِض مكتبة Google Sign-In للنظام الأساسي أو مكتبة عميل Google API لسمة JavaScript أو طلبات الاتصال المباشرة بنقاط نهاية Google Auth 2.0 كلاً من رمز الوصول OAuth 2.0 ورمز تعريف OpenID Connect في ردّ واحد.

مثال على استجابة تحتوي على 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"
  }

بيانات اعتماد Google Identity Services

تعرِض مكتبة Google Identity Services ما يلي:

  • رمز دخول عند استخدامه للتفويض:

    {
      "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"
    }
    

استجابة الرمز المميّز غير صالحة

مثال على استجابة من Google عند محاولة إرسال طلب لواجهة برمجة التطبيقات باستخدام رمز مميّز للوصول منتهي الصلاحية أو مُلغى أو غير صالح:

عناوين استجابة 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"
    }
  }