نظرة عامة
للحصول على رمز مميّز للوصول لكل مستخدم من أجل طلب Google APIs، تقدّم Google عدة مكتبات JavaScript:
يقدّم هذا الدليل تعليمات لنقل البيانات من هذه المكتبات إلى مكتبة Google Identity Services.
باتّباع هذا الدليل، ستتمكّن من:
- استبدال مكتبة المنصة المتوقفة نهائيًا بمكتبة خدمات إدارة الهوية، و
- في حال استخدام مكتبة عميل واجهة برمجة التطبيقات، عليك إزالة وحدة
gapi.auth2المتوقّفة نهائيًا وطرقها وعناصرها، واستبدالها بما يعادلها من خدمات إدارة الهوية.
للاطّلاع على وصف للتغييرات التي طرأت على مكتبة JavaScript لخدمات إدارة الهوية، يُرجى قراءة النظرة العامة وطريقة عمل تفويض المستخدم لمراجعة المصطلحات والمفاهيم الرئيسية.
إذا كنت تبحث عن مصادقة لتسجيل المستخدمين وتسجيل الدخول، يُرجى الاطّلاع على نقل البيانات من ميزة "تسجيل الدخول باستخدام حساب Google" بدلاً من ذلك.
تحديد مسار التفويض
هناك مساران محتملان لتفويض المستخدم: ضمني ورمز التفويض.
راجِع تطبيق الويب لتحديد نوع مسار التفويض المستخدَم.
مؤشرات على أنّ تطبيق الويب يستخدم التدفّق الضمني:
- يعتمد تطبيق الويب على المتصفّح فقط، ولا يتضمّن منصة خلفية.
- يجب أن يكون المستخدم حاضرًا لطلب Google APIs، ويستخدم تطبيقك رموز الدخول فقط، ولا يتطلّب رموزًا مميزة لإعادة التحميل.
- يتم تحميل تطبيق الويب
apis.google.com/js/api.js. - يستند التنفيذ إلى OAuth 2.0 لتطبيقات الويب من جهة العميل.
- يستخدم تطبيقك إما وحدات
gapi.clientأوgapi.auth2المتوفّرة في مكتبة عملاء Google API للغة JavaScript.
في ما يلي مؤشرات على أنّ تطبيق الويب يستخدم مسار رمز التفويض:
تستند عملية التنفيذ إلى:
يتم تنفيذ تطبيقك في متصفّح المستخدم وعلى منصة الخلفية.
تستضيف منصة الخلفية نقطة نهاية لرمز التفويض.
تطلب منصة الخلفية Google APIs نيابةً عن المستخدمين بدون الحاجة إلى تواجدهم، وهو ما يُعرف أيضًا باسم وضع عدم الاتصال بالإنترنت.
تتم إدارة الرموز المميزة لإعادة التحميل وتخزينها من خلال منصة الخلفية.
في بعض الحالات، قد تتيح قاعدة الرموز البرمجية كلا المسارَين.
اختيار مسار تفويض
قبل بدء عملية نقل البيانات، عليك تحديد ما إذا كان من الأفضل لك مواصلة استخدام سير العمل الحالي أو اعتماد سير عمل مختلف لتلبية احتياجاتك.
راجِع اختيار مسار تفويض لفهم الاختلافات الرئيسية والمفاضلات بين المسارَين.
في معظم الحالات، يُنصح باستخدام مسار رمز التفويض لأنّه يوفّر أعلى مستوى من الأمان للمستخدم. يؤدي تنفيذ هذا الإجراء أيضًا إلى تمكين منصتك من إضافة وظائف جديدة بلا إنترنت، مثل جلب التحديثات لإعلام المستخدمين بالتغييرات الملحوظة في التقويم والصور والاشتراكات.
اختَر مسار تفويض باستخدام أدوات الاختيار.
التدفّق الضمني
الحصول على رمز دخول للاستخدام داخل المتصفّح أثناء تواجد المستخدم
تعرض أمثلة على التدفّق الضمني تطبيقات الويب قبل نقل البيانات إلى "خدمات إدارة الهوية" وبعده.
مسار رمز التفويض
يتم إرسال رمز تفويض لكل مستخدم صادر عن 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.auth2informationalتسجيل استخدام الوظائف المتوقّفة نهائيًا في وحدة تحكّم JS يمكنك أيضًا تسجيل البيانات في مساحة تخزين الجلسة عند ضبط اسم مفتاح اختياري: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 للغة JavaScript بأمان، والاستفادة من ميزة الإنشاء التلقائي لأساليب JS القابلة للاستدعاء من مستند استكشاف، وتجميع طلبات متعددة من واجهة برمجة التطبيقات، ووظيفة إدارة CORS.
بسكويت
لا يتطلّب تفويض المستخدم استخدام ملفات تعريف الارتباط.
يمكنك الاطّلاع على مقالة نقل البيانات من ميزة "تسجيل الدخول باستخدام حساب Google" للحصول على تفاصيل حول كيفية استخدام مصادقة المستخدم لملفات تعريف الارتباط، ومقالة كيفية استخدام Google لملفات تعريف الارتباط للتعرّف على كيفية استخدام ملفات تعريف الارتباط في منتجات Google وخدماتها الأخرى.
بيانات الاعتماد
تفصل خدمات الهوية في Google بين مصادقة المستخدم وتفويضه في عمليتين مختلفتين، وتكون بيانات اعتماد المستخدم منفصلة: يتم عرض رمز التعريف المستخدَم لتحديد هوية المستخدم بشكل منفصل عن رمز الوصول المستخدَم للتفويض.
للاطّلاع على هذه التغييرات، يُرجى مراجعة مثال على بيانات الاعتماد.
التدفّق الضمني
يمكنك الفصل بين مصادقة المستخدم وتفويضه من خلال إزالة معالجة ملف المستخدم الشخصي من مسارات التفويض.
أزِل مراجع عميل JavaScript لميزة "تسجيل الدخول باستخدام حساب Google" التالية:
الطُرق
GoogleUser.getBasicProfile()GoogleUser.getId()
مسار رمز التفويض
تفصل "خدمات إدارة الهوية" بيانات الاعتماد داخل المتصفّح إلى رمز مميّز للمعرّف ورمز مميّز للوصول. لا ينطبق هذا التغيير على بيانات الاعتماد التي يتم الحصول عليها من خلال طلبات مباشرة إلى نقاط نهاية Google OAuth 2.0 من منصة الخلفية أو من خلال المكتبات التي تعمل على خادم آمن على منصتك، مثل عميل Node.js لواجهات برمجة تطبيقات Google.
حالة الجلسة
في السابق، كانت ميزة "تسجيل الدخول باستخدام حساب 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.ClientConfiggapi.auth2.OfflineAccessOptions
الطُرق:
gapi.auth2.getAuthInstance()GoogleUser.grant()
التدفّق الضمني
أضِف عنصر TokenClientConfig وطلب initTokenClient() لضبط تطبيق الويب، باتّباع المثال الوارد في إعداد برنامج الرمز المميّز.
استبدِل مراجع عميل JavaScript لتسجيل الدخول باستخدام حساب Google بـ 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.
عند التبديل من مسار المنح الضمني إلى مسار رمز التفويض:
إزالة مراجع عميل JavaScript لميزة "تسجيل الدخول باستخدام حساب Google"
العناصر:
gapi.auth2.AuthorizeConfig
الطُرق:
gapi.auth2.init()
المَعلمات:
gapi.auth2.AuthorizeConfig.login_hintgapi.auth2.GoogleUser.getHostedDomain()
طلب الرمز المميّز
يؤدي الإجراء التفاعلي من المستخدم، مثل النقر على زر، إلى إنشاء طلب ينتج عنه إرجاع رمز مميز للوصول مباشرةً إلى متصفّح المستخدم من خلال التدفّق الضمني، أو إلى منصة الخلفية بعد استبدال رمز التفويض لكل مستخدم برمز مميز للوصول ورمز مميز لإعادة التحميل.
التدفّق الضمني
يمكن الحصول على رموز الدخول واستخدامها في المتصفّح عندما يكون المستخدم مسجّلاً الدخول ولديه جلسة نشطة مع Google. في الوضع الضمني، يجب أن يتّخذ المستخدم إجراءً تفاعليًا لطلب رمز مميّز للوصول، حتى إذا كان هناك طلب سابق.
استبدال مراجع عميل JavaScript لتسجيل الدخول باستخدام حساب Google: بـ 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 التي تعذّر إجراؤها عند استخدام رمز دخول منتهي الصلاحية أو ملغى، ولطلب رمز دخول جديد صالح.
تعرض Google APIs رمز حالة HTTP 401 Unauthorized ورسالة الخطأ invalid_token عند استخدام رمز دخول منتهي الصلاحية أو تم إبطاله. للاطّلاع على مثال، يُرجى مراجعة الردّ على رمز مميّز غير صالح.
الرموز المميّزة المنتهية الصلاحية
تكون رموز الدخول قصيرة الأجل، وغالبًا ما تكون صالحة لبضع دقائق فقط.
إبطال الرمز المميّز
يمكن لصاحب حساب Google إلغاء الموافقة التي منحها سابقًا في أي وقت. ويؤدي ذلك إلى إبطال رموز الدخول والرموز المميزة لإعادة التحميل الحالية. يمكن بدء عملية الإبطال من منصتك باستخدام revoke() أو من خلال حساب Google.
استبدال مراجع عميل JavaScript لتسجيل الدخول باستخدام حساب Google: بـ Google Identity Services:
الطُرق:
getAuthInstance().disconnect()معgoogle.accounts.oauth2.revoke()GoogleUser.disconnect()معgoogle.accounts.oauth2.revoke()
يمكنك استدعاء revoke عندما يحذف مستخدم حسابه على منصتك أو
يريد إزالة الموافقة على مشاركة البيانات مع تطبيقك.
طلب موافقة المستخدم
تعرض Google مربّع إفادة الموافقة للمستخدم عندما يطلب تطبيق الويب أو المنصة الخلفية رمز الدخول. يمكنك الاطّلاع على أمثلة على مربّعات إفادة الموافقة التي تعرضها Google للمستخدمين.
قبل إصدار رمز مميّز للوصول إلى تطبيقك، يجب أن تكون هناك جلسة Google حالية ونشطة لطلب موافقة المستخدم وتسجيل النتيجة. قد يُطلب من المستخدم تسجيل الدخول إلى حساب Google إذا لم تكن هناك جلسة حالية.
تسجيل دخول المستخدم
قد يكون المستخدمون مسجّلين الدخول إلى حساب Google في علامة تبويب متصفّح منفصلة أو بشكلٍ أصلي من خلال متصفّح أو نظام تشغيل. ننصحك بإضافة ميزة تسجيل الدخول باستخدام حساب Google إلى موقعك الإلكتروني لإنشاء جلسة نشطة بين حساب Google والمتصفّح عندما يفتح المستخدم تطبيقك لأول مرة، ما يوفّر المزايا التالية:
- يقلّل من عدد المرات التي يجب فيها على المستخدم تسجيل الدخول، ويؤدي طلب رمز الدخول إلى بدء عملية تسجيل الدخول إلى حساب Google إذا لم تكن هناك جلسة نشطة من قبل.
- الاستخدام المباشر لحقل credential
emailالخاص برمز تعريف JWT كقيمة لمَعلمةlogin_hintفي كائناتCodeClientConfigأوTokenClientConfigويكون ذلك مفيدًا بشكل خاص إذا لم تكن منصتك تتضمّن نظامًا لإدارة حسابات المستخدمين. - البحث عن حساب Google وربطه بحساب مستخدم محلي حالي على منصتك، ما يساعد في تقليل الحسابات المكرّرة على منصتك
- عند إنشاء حساب محلي جديد، يمكن فصل مربّعات الحوار ومسار الاشتراك بوضوح عن مربّعات الحوار ومسارات مصادقة المستخدم، ما يقلّل من عدد الخطوات المطلوبة ويحسّن معدّل الانسحاب.
بعد تسجيل الدخول وقبل إصدار رمز الدخول، يجب أن يمنح المستخدمون موافقتهم لتطبيقك على النطاقات المطلوبة.
ردّ الرمز المميز والموافقة
بعد الحصول على الموافقة، يتم عرض رمز مميّز للوصول مع قائمة بالنطاقات التي وافق عليها المستخدم أو رفضها.
تتيح الأذونات الدقيقة للمستخدمين الموافقة على نطاقات فردية أو رفضها. عند طلب الوصول إلى نطاقات متعددة، يتم منح كل نطاق أو رفضه بشكل مستقل عن النطاقات الأخرى. استنادًا إلى خيار المستخدم، يفعّل تطبيقك بشكل انتقائي الميزات والوظائف التي تعتمد على نطاق فردي.
التدفّق الضمني
استبدِل مراجع عميل JavaScript لتسجيل الدخول باستخدام حساب Google بـ Google Identity Services:
العناصر:
gapi.auth2.AuthorizeResponseمعTokenClient.TokenResponsegapi.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>
مكتبة برامج JS
OAuth 2.0 لتطبيقات الويب من جهة العميل التي تعمل في المتصفّح باستخدام مربّع حوار منبثق للحصول على موافقة المستخدم
يتم تحميل وحدة gapi.auth2 يدويًا.
<!DOCTYPE html>
<html><head></head><body>
<script>
var GoogleAuth;
var SCOPE = 'https://www.googleapis.com/auth/drive.metadata.readonly';
function handleClientLoad() {
// Load the API's client and auth2 modules.
// Call the initClient function after the modules load.
gapi.load('client:auth2', initClient);
}
function initClient() {
// In practice, your app can retrieve one or more discovery documents.
var discoveryUrl = 'https://www.googleapis.com/discovery/v1/apis/drive/v3/rest';
// Initialize the gapi.client object, which app uses to make API requests.
// Get API key and client ID from Google Cloud console.
// 'scope' field specifies space-delimited list of access scopes.
gapi.client.init({
'apiKey': 'YOUR_API_KEY',
'clientId': 'YOUR_CLIENT_ID',
'discoveryDocs': [discoveryUrl],
'scope': SCOPE
}).then(function () {
GoogleAuth = gapi.auth2.getAuthInstance();
// Listen for sign-in state changes.
GoogleAuth.isSignedIn.listen(updateSigninStatus);
// Handle initial sign-in state. (Determine if user is already signed in.)
var user = GoogleAuth.currentUser.get();
setSigninStatus();
// Call handleAuthClick function when user clicks on
// "Sign In/Authorize" button.
$('#sign-in-or-out-button').click(function() {
handleAuthClick();
});
$('#revoke-access-button').click(function() {
revokeAccess();
});
});
}
function handleAuthClick() {
if (GoogleAuth.isSignedIn.get()) {
// User is authorized and has clicked "Sign out" button.
GoogleAuth.signOut();
} else {
// User is not signed in. Start Google auth flow.
GoogleAuth.signIn();
}
}
function revokeAccess() {
GoogleAuth.disconnect();
}
function setSigninStatus() {
var user = GoogleAuth.currentUser.get();
var isAuthorized = user.hasGrantedScopes(SCOPE);
if (isAuthorized) {
$('#sign-in-or-out-button').html('Sign out');
$('#revoke-access-button').css('display', 'inline-block');
$('#auth-status').html('You are currently signed in and have granted ' +
'access to this app.');
} else {
$('#sign-in-or-out-button').html('Sign In/Authorize');
$('#revoke-access-button').css('display', 'none');
$('#auth-status').html('You have not authorized this app or you are ' +
'signed out.');
}
}
function updateSigninStatus() {
setSigninStatus();
}
</script>
<button id="sign-in-or-out-button"
style="margin-left: 25px">Sign In/Authorize</button>
<button id="revoke-access-button"
style="display: none; margin-left: 25px">Revoke access</button>
<div id="auth-status" style="display: inline; padding-left: 25px"></div><hr>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body></html>
نقاط نهاية OAuth 2.0
بروتوكول OAuth 2.0 لتطبيقات الويب من جهة العميل التي تعمل في المتصفّح باستخدام عمليات إعادة التوجيه إلى خادم تفويض 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 the Google authorization 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 the Google authorization 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 APIs.
<!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 للغة JavaScript.
يتم استخدام Promises وasync و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>
معاودة الاتصال بواجهة برمجة التطبيقات GAPI
يوضّح هذا المثال كيفية إضافة مكتبة Google Identity Service باستخدام نموذج الرمز المميّز، وإزالة وحدة gapi.auth2، واستدعاء واجهة برمجة تطبيقات باستخدام مكتبة برامج Google API للغة 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 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 the Google authorization 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();
}
الطريقة الجديدة
تجربة المستخدم في النافذة المنبثقة لخدمة GIS
يعرض هذا المثال مكتبة 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;
function initClient() {
client = google.accounts.oauth2.initCodeClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
ux_mode: 'popup',
callback: (response) => {
var code_receiver_uri = 'YOUR_AUTHORIZATION_CODE_ENDPOINT_URI',
// Send auth code to your backend platform
const xhr = new XMLHttpRequest();
xhr.open('POST', code_receiver_uri, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onload = function() {
console.log('Signed in as: ' + xhr.responseText);
};
xhr.send('code=' + response.code);
// After receipt, the code is exchanged for an access token and
// refresh token, and the platform then updates this web app
// running in user's browser with the requested calendar info.
},
});
}
function getAuthCode() {
// Request authorization code and obtain user consent
client.requestCode();
}
</script>
<button onclick="getAuthCode();">Load Your Calendar</button>
</body>
</html>
تجربة المستخدم لإعادة التوجيه في GIS
يتيح نموذج رمز التفويض استخدام وضعَي تجربة المستخدم "النافذة المنبثقة" و"إعادة التوجيه" لإرسال رمز تفويض لكل مستخدم إلى نقطة النهاية التي تستضيفها منصتك. يظهر وضع تجربة المستخدم لإعادة التوجيه هنا:
<!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 واحدة تُستخدم لمصادقة المستخدمين وتفويضهم، وتجمع بين الميزات والوظائف المتوفّرة في عدة مكتبات ووحدات مختلفة وتحلّ محلّها:
الإجراءات التي يجب اتخاذها عند نقل البيانات إلى "خدمات إدارة الهوية":
| مكتبة JS الحالية | مكتبة JS جديدة | ملاحظات |
|---|---|---|
apis.google.com/js/api.js |
accounts.google.com/gsi/client |
أضِف مكتبة جديدة واتّبِع التدفّق الضمني. |
apis.google.com/js/client.js |
accounts.google.com/gsi/client |
أضِف مكتبة جديدة واتّبِع مسار رمز التفويض. |
مرجع سريع للمكتبة
مقارنة بين العناصر والطرق في مكتبة عميل JavaScript لتسجيل الدخول باستخدام حساب Google القديمة ومكتبة خدمات الهوية من 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() أو 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() أو requestAccessToken() |
استبدال القديم بالجديد |
gapi.auth2.ClientConfig() |
TokenClientConfig أو CodeClientConfig |
استبدال القديم بالجديد |
gapi.auth2.getAuthInstance() |
إزالة | |
gapi.auth2.init() |
initTokenClient() أو initCodeClient() |
استبدال القديم بالجديد |
عنصر واحد (gapi.auth2.OfflineAccessOptions) |
إزالة | |
عنصر واحد (gapi.auth2.SignInOptions) |
إزالة | |
عنصر gapi.signin2 والطرق المرتبطة به: |
||
gapi.signin2.render() |
إزالة. يؤدي تحميل HTML DOM لعنصر g_id_signin أو طلب JS إلى 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"
}
}