نظرة عامة
للحصول على رمز مميز للوصول لكل مستخدم من أجل استدعاء واجهات Google API، توفّر Google عدة مكتبات JavaScript:
يقدّم هذا الدليل تعليمات لنقل البيانات من هذه المكتبات إلى مكتبة Google Identity Services.
باتّباع هذا الدليل، ستتمكّن من:
- استبدِل Platform Library المتوقّفة نهائيًا بمكتبة Identity Services، و
- في حال استخدام "مكتبة برامج API"، عليك إزالة الوحدة
gapi.auth2
المتوقّفة نهائيًا، وطُرقها وعناصرها، واستبدالها بمكافئاتها في "خدمات تحديد الهوية".
للحصول على وصف للتغييرات التي تم إجراؤها على مكتبة JavaScript الخاصة بخدمات تحديد الهوية، يُرجى قراءة النظرة العامة وطريقة عمل تفويض المستخدم لمراجعة المصطلحات والمفاهيم الأساسية.
إذا كنت تبحث عن مصادقة لتسجيل المستخدمين وإنشاء حساباتهم، اطّلِع على مقالة نقل البيانات من ميزة "تسجيل الدخول باستخدام حساب Google" بدلاً من ذلك.
تحديد مسار التفويض
هناك مساران محتملان لتفويض المستخدم، وهما التفويض الضمني والتفويض باستخدام رمز التفويض.
راجِع تطبيق الويب لتحديد نوع عملية منح الإذن المستخدَمة.
مؤشرات على أنّ تطبيق الويب يستخدم التدفق الضمني:
- تطبيق الويب يستند بشكل كامل إلى المتصفّح، بدون أي نظام أساسي للخادم الخلفي.
- يجب أن يكون المستخدم متواجدًا عند طلب بيانات من واجهات Google API، ويجب أن يستخدم تطبيقك رموز الدخول فقط، ولا يتطلّب رموزًا مميزة لإعادة التحميل.
- يتم تحميل تطبيق الويب
apis.google.com/js/api.js
. - يستند التنفيذ إلى بروتوكول OAuth 2.0 لتطبيقات الويب من جهة العميل.
- يستخدم تطبيقك الوحدة
gapi.client
أو الوحدةgapi.auth2
المتوفّرة في Google API Client Library for JavaScript.
مؤشرات على أنّ تطبيق الويب يستخدم مسار رمز التفويض:
تستند عملية التنفيذ إلى ما يلي:
يتم تنفيذ تطبيقك في متصفّح المستخدم وعلى منصة الخلفية.
تستضيف منصة الخلفية نقطة نهاية لرمز التفويض.
تطلب منصة الخلفية بيانات من واجهات برمجة تطبيقات Google نيابةً عن المستخدمين بدون الحاجة إلى أن يكونوا متواجدين، ويُعرف ذلك أيضًا باسم وضع عدم الاتصال بالإنترنت.
تتولّى منصة الخلفية إدارة رموز التحديث وتخزينها.
في بعض الحالات، قد يتوافق رمزك الأساسي مع كلا المسارين.
اختيار عملية تفويض
قبل بدء عملية نقل البيانات، عليك تحديد ما إذا كان من الأفضل مواصلة استخدام مسار التحويل الحالي أو اعتماد مسار مختلف لتلبية احتياجاتك على أفضل وجه.
راجِع اختيار مسار تفويض للتعرّف على الاختلافات الرئيسية والمفاضلات بين المسارين.
في معظم الحالات، يُنصح باستخدام مسار رمز التفويض لأنّه يوفّر أعلى مستوى من أمان المستخدم. يتيح تنفيذ هذا المسار أيضًا لمنصتك إضافة وظائف جديدة غير متصلة بالإنترنت، مثل جلب التحديثات لإعلام المستخدمين بالتغييرات المهمة في تقويمهم وصورهم واشتراكاتهم.
اختَر مسار تفويض باستخدام أدوات الاختيار.
التدفّق الضمني
الحصول على رمز دخول لاستخدامه في المتصفّح أثناء تواجد المستخدم
تعرض أمثلة على التدفق الضمني تطبيقات الويب قبل وبعد نقلها إلى "خدمات تحديد الهوية".
مسار رمز التفويض
يتم تسليم رمز تفويض لكل مستخدم صادر عن Google إلى منصة الخلفية، حيث يتم استبداله برمز دخول ورمز إعادة تحميل.
تعرض أمثلة على تدفّق رمز التفويض تطبيقات الويب قبل وبعد نقلها إلى "خدمات إدارة الهوية".
في هذا الدليل، اتّبِع التعليمات المكتوبة بخط غليظ لإضافة أو إزالة أو تعديل أو استبدال الوظائف الحالية.
التغييرات التي أُجريت على تطبيق الويب داخل المتصفّح
يراجع هذا القسم التغييرات التي ستجريها على تطبيق الويب داخل المتصفّح عند نقل البيانات إلى مكتبة JavaScript الخاصة بخدمات Google Identity.
تحديد الرمز البرمجي المتأثر واختباره
يمكن أن تساعد ملفات تعريف الارتباط المخصّصة لتصحيح الأخطاء في تحديد موقع الرمز البرمجي المتأثّر واختبار السلوك بعد إيقاف الميزة نهائيًا.
في التطبيقات الكبيرة أو المعقّدة، قد يكون من الصعب العثور على جميع الرموز المتأثرة بإيقاف الوحدة 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".
أضِف مكتبة "خدمات تحديد الهوية" إلى تطبيق الويب الخاص بك من خلال تضمينها في المستند على النحو التالي:
<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 Library for JavaScript والاستفادة من ميزة الإنشاء التلقائي
لطُرق JS قابلة للاستدعاء من مستند استكشاف، وتجميع عدة طلبات بيانات من واجهة برمجة التطبيقات،
ووظيفة إدارة CORS.
بسكويت
لا يتطلّب تفويض المستخدم استخدام ملفات تعريف الارتباط.
اطّلِع على مقالة نقل البيانات من خدمة "تسجيل الدخول باستخدام حساب Google" لمعرفة تفاصيل حول كيفية استخدام ملفات تعريف الارتباط في مصادقة المستخدم، ومقالة كيفية استخدام Google لملفات تعريف الارتباط لمعرفة كيفية استخدام ملفات تعريف الارتباط في منتجات وخدمات Google الأخرى.
بيانات الاعتماد
تفصل "خدمات هوية Google" بين مصادقة المستخدم وترخيصه في عمليتين مختلفتين، كما أنّ بيانات اعتماد المستخدم منفصلة: يتم عرض الرمز المميز للمعرّف المستخدَم لتحديد هوية المستخدم بشكل منفصل عن رمز الدخول المستخدَم للترخيص.
للاطّلاع على هذه التغييرات، راجِع بيانات الاعتماد النموذجية.
التدفّق الضمني
فصل مصادقة المستخدمين عن تفويضهم من خلال إزالة معالجة الملف الشخصي للمستخدم من مسارات التفويض
أزِل مراجع عميل JavaScript في ميزة "تسجيل الدخول باستخدام حساب Google" التالية:
الطُرق
GoogleUser.getBasicProfile()
GoogleUser.getId()
مسار رمز التفويض
تفصل "خدمات التحقّق من الهوية" بيانات الاعتماد داخل المتصفّح إلى رمز مميّز للمعرّف ورمز مميّز للوصول. لا ينطبق هذا التغيير على بيانات الاعتماد التي يتم الحصول عليها من خلال طلبات مباشرة إلى نقاط نهاية Google OAuth 2.0 من منصة الخلفية أو من خلال المكتبات التي تعمل على خادم آمن على منصتك، مثل Google APIs Node.js Client.
حالة الجلسة
في السابق، كانت ميزة "تسجيل الدخول باستخدام حساب Google" تساعدك في إدارة حالة تسجيل دخول المستخدم باستخدام ما يلي:
- معالجات معاودة الاتصال لمراقبة حالة جلسة المستخدم
- أدوات معالجة للأحداث والتغييرات في حالة تسجيل الدخول لحساب 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()
لتحديد إعدادات تطبيق الويب، باتّباع المثال الوارد في تهيئة برنامج
العميل الخاص بالرمز المميز.
استبدِل مراجع برنامج Google Sign-In JavaScript بـ Google Identity Services:
العناصر:
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.
عند التبديل من التدفق الضمني إلى تدفق رمز التفويض:
إزالة مراجع برنامج Google Sign-In JavaScript
العناصر:
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 رمز حالة HTTP 401 Unauthorized
ورسالة الخطأ invalid_token
عند استخدام رمز دخول منتهي الصلاحية أو تم إبطاله. للاطّلاع على مثال، راجِع ردّ الرمز المميّز غير الصالح.
الرموز المميزة المنتهية الصلاحية
تكون رموز الدخول قصيرة الأجل، وغالبًا ما تكون صالحة لبضع دقائق فقط.
إبطال الرمز المميز
في أي وقت، يمكن لصاحب حساب Google إلغاء الموافقة التي سبق أن منحها. سيؤدي ذلك إلى إبطال رموز الدخول ورموز إعادة التحميل الحالية. يمكن أن يتم إبطال الشهادة من خلال منصتك باستخدام revoke()
أو من خلال حساب Google.
استبدال مراجع برنامج Google Sign-In JavaScript بـ Google Identity Services:
الطرق:
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 وربطه بحساب مستخدم محلي حالي على منصتك، ما يساعد في الحدّ من الحسابات المكرّرة على منصتك
- عند إنشاء حساب محلي جديد، يمكن فصل مربّعات الحوار والخطوات الخاصة بالاشتراك بوضوح عن مربّعات الحوار والخطوات الخاصة بمصادقة المستخدم، ما يقلّل عدد الخطوات المطلوبة ويحسّن معدّل التوقف.
بعد تسجيل الدخول وقبل إصدار رمز دخول، يجب أن يقدّم المستخدمون موافقتهم على النطاقات المطلوبة لتطبيقك.
الرمز المميز وردّ الموافقة
بعد الحصول على الموافقة، يتم عرض رمز مميّز للوصول مع قائمة بالنطاقات التي وافق عليها المستخدم أو رفضها.
تسمح الأذونات الدقيقة للمستخدمين بالموافقة على النطاقات الفردية أو رفضها. عند طلب الوصول إلى نطاقات متعدّدة، يتم منح أو رفض كل نطاق بشكل مستقل عن النطاقات الأخرى. استنادًا إلى اختيار المستخدم، يفعّل تطبيقك بشكل انتقائي الميزات والوظائف التي تعتمد على نطاق فردي.
التدفّق الضمني
استبدِل مراجع برنامج Google Sign-In JavaScript بـ Google Identity Services:
العناصر:
gapi.auth2.AuthorizeResponse
معTokenClient.TokenResponse
gapi.auth2.AuthResponse
معTokenClient.TokenResponse
الطرق:
-
GoogleUser.hasGrantedScopes()
معgoogle.accounts.oauth2.hasGrantedAllScopes()
-
GoogleUser.getGrantedScopes()
معgoogle.accounts.oauth2.hasGrantedAllScopes()
إزالة مراجع برنامج Google Sign-In JavaScript:
الطرق:
GoogleUser.getAuthResponse()
عدِّل تطبيق الويب الخاص بك باستخدام hasGrantedAllScopes()
وhasGrantedAnyScope()
باتّباع مثال الأذونات الدقيقة هذا.
مسار رمز التفويض
عدِّل أو أضِف نقطة نهاية لرمز التفويض إلى منصة الخلفية باتّباع التعليمات الواردة في التعامل مع رمز التفويض.
عدِّل منصتك لتنفيذ الخطوات الموضّحة في دليل استخدام نموذج الرمز من أجل التحقّق من صحة الطلب والحصول على رمز دخول ورمز مميز لإعادة التحقّق.
عدِّل منصتك لتفعيل الميزات والوظائف أو إيقافها بشكل انتقائي استنادًا إلى النطاقات الفردية التي وافق عليها المستخدم باتّباع التعليمات الخاصة بالتفويض المتزايد وفحص نطاقات الوصول التي منحها المستخدم.
أمثلة على التدفّق الضمني
الطريقة القديمة
مكتبة برامج GAPI
مثال على Google API Client Library for 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>
مكتبة برامج 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
الإصدار 2.0 من OAuth لتطبيقات الويب من جهة العميل التي تعمل في المتصفّح باستخدام عمليات إعادة التوجيه إلى 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>
الطريقة الجديدة
GIS فقط
يعرض هذا المثال مكتبة JavaScript الخاصة بخدمة Google Identity Service باستخدام نموذج الرمز المميز ومربّع الحوار المنبثق لطلب موافقة المستخدم. يتم توفيرها لتوضيح الحد الأدنى من الخطوات المطلوبة لإعداد عميل وطلب رمز دخول والحصول عليه واستدعاء إحدى واجهات Google 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 async/await
يوضّح هذا المثال كيفية إضافة مكتبة Google Identity Service باستخدام
نموذج الرمز المميز وإزالة الوحدة gapi.auth2
واستدعاء واجهة برمجة تطبيقات باستخدام
Google API Client Library for JavaScript.
يتم استخدام الوعود والوظائف غير المتزامنة وعبارة await لفرض ترتيب تحميل المكتبة ولرصد أخطاء التفويض وإعادة المحاولة. لا يتم طلب بيانات من واجهة برمجة التطبيقات إلا بعد توفّر رمز دخول صالح.
من المتوقّع أن يضغط المستخدمون على الزر "عرض التقويم" عندما تكون رمز الدخول غير متوفّر عند تحميل الصفحة للمرة الأولى، أو في وقت لاحق بعد انتهاء صلاحية رمز الدخول.
<!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>
معاودة الاتصال بواجهة برمجة التطبيقات في Google
يوضّح هذا المثال كيفية إضافة مكتبة Google Identity Service باستخدام
نموذج الرمز المميز وإزالة الوحدة gapi.auth2
واستدعاء واجهة برمجة تطبيقات باستخدام
Google API Client Library for JavaScript.
تُستخدَم المتغيّرات لفرض ترتيب تحميل المكتبة. يتم إجراء طلبات 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>
أمثلة على مسار رمز التفويض
يمكن أن تستخدم تجربة المستخدم المنبثقة لمكتبة Google Identity Service عملية إعادة توجيه عنوان 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 <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 باستخدام نموذج رمز التفويض، وهو عبارة عن مربّع حوار منبثق لطلب موافقة المستخدم ومعالج لإعادة الاتصال لتلقّي رمز التفويض من 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 واحدة تُستخدَم في مصادقة المستخدمين وتفويضهم، وهي تجمع الميزات والوظائف المتوفّرة في العديد من المكتبات والوحدات المختلفة وتستبدلها:
- عميل JavaScript في خدمة "تسجيل الدخول باستخدام حساب Google"
- مكتبة برامج Google API Client Library للغة JavaScript
الإجراءات التي يجب اتّخاذها عند نقل البيانات إلى "خدمات إدارة الهوية":
مكتبة JavaScript الحالية | مكتبة 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 JavaScript القديمة ومكتبة خدمات هوية Google الجديدة، بالإضافة إلى ملاحظات تتضمّن معلومات إضافية والإجراءات التي يجب اتّخاذها أثناء عملية نقل البيانات
الإصدار القديم | جديد | ملاحظات |
---|---|---|
عنصر 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 أو طلب JavaScript إلى google.accounts.id.renderButton إلى بدء عملية تسجيل دخول المستخدم إلى حساب Google. |
مثال على بيانات الاعتماد
بيانات الاعتماد الحالية
تعرض مكتبة منصة "تسجيل الدخول باستخدام حساب Google" أو مكتبة برامج Google API للغة JavaScript أو عمليات طلب مباشرة إلى نقاط نهاية Google OAuth 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"
}
}