يسترد برنامج تسجيل الدخول بنقرة واحدة الرمز المميّز لمعرّف Google عندما يختار المستخدم حسابًا على Google. الرمز المميّز للمعرّف هو تأكيد موقَّع لهوية المستخدم، ويحتوي أيضًا على معلومات الملف الشخصي الأساسية للمستخدم، وقد يتضمن عنوان بريد إلكتروني تم التحقق منه من قِبل Google.
عند توفّر الرموز المميّزة لرقم التعريف، يمكنك استخدامها للمصادقة بأمان باستخدام الخلفية لتطبيقك، أو لتسجيل المستخدم تلقائيًا للحصول على حساب جديد بدون الحاجة إلى إثبات ملكية عنوان البريد الإلكتروني للمستخدم.
لتسجيل الدخول أو اشتراك مستخدم باستخدام الرمز المميّز للمعرّف، أرسِل الرمز المميّز إلى الواجهة الخلفية لتطبيقك. في الخلفية، تحقَّق من الرمز المميّز باستخدام مكتبة عميل واجهة Google API أو مكتبة JWT للأغراض العامة. إذا لم يسجّل المستخدم الدخول إلى تطبيقك باستخدام حساب Google هذا من قبل، أنشئ حسابًا جديدًا.
إذا اخترت بشكل اختياري استخدام رقم واحد للمساعدة في تجنّب إعادة تشغيل الهجمات، يمكنك استخدام getNonce لإرساله مع الرمز المميّز للمعرِّف إلى الخادم الخلفي، والتحقّق من القيمة المتوقّعة. ننصحك بالتفكير بشدّة في استخدام nonce لتحسين أمان المستخدم وأمانه.
الحصول على رمز مميز للمعرّف من كائن بيانات الاعتماد
بعد استرداد بيانات اعتماد المستخدم، تحقق مما إذا كان كائن بيانات الاعتماد يتضمن رمزًا مميزًا للمعرف. إذا كان الأمر كذلك، فأرسله إلى الخادم الخلفي.
Java
public class YourActivity extends AppCompatActivity { // ... private static final int REQ_ONE_TAP = 2; // Can be any integer unique to the Activity. private boolean showOneTapUI = true; // ... @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_ONE_TAP: try { SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data); String idToken = credential.getGoogleIdToken(); if (idToken != null) { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token."); } } catch (ApiException e) { // ... } break; } } }
Kotlin
class YourActivity : AppCompatActivity() { // ... private val REQ_ONE_TAP = 2 // Can be any integer unique to the Activity private var showOneTapUI = true // ... override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { REQ_ONE_TAP -> { try { val credential = oneTapClient.getSignInCredentialFromIntent(data) val idToken = credential.googleIdToken when { idToken != null -> { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token.") } else -> { // Shouldn't happen. Log.d(TAG, "No ID token!") } } } catch (e: ApiException) { // ... } } } // ... }
التحقّق من صحة الرمز المميّز للمعرّف
بعد تلقّي الرمز المميّز للمعرّف عبر HTTPS POST، يجب التحقّق من صحّة الرمز المميّز.
للتحقّق من صلاحية الرمز المميّز، احرص على استيفاء المعايير التالية:
- وقّعت Google الرمز المميّز لرقم التعريف بشكل صحيح. استخدِم مفاتيح Google العامة
(المتوفّرة بتنسيق
JWK أو
PEM)
للتحقّق من توقيع الرمز المميّز. يتم تدوير هذه المفاتيح بانتظام، لذا يمكنك فحص عنوان
Cache-Control
في الاستجابة لتحديد الوقت المناسب لاستردادها مرة أخرى. - قيمة
aud
في الرمز المميّز للرقم التعريفي تساوي أحد معرِّفات عملاء تطبيقك. وتُعدّ عملية التحقّق هذه ضرورية لمنع الرموز المميّزة لرقم التعريف التي يتم إصدارها لتطبيق ضار عند استخدامها للوصول إلى بيانات المستخدم نفسه على خادم الخلفية في تطبيقك. - قيمة
iss
في الرمز المميّز للمعرّف تساويaccounts.google.com
أوhttps://accounts.google.com
. - لم يمر وقت انتهاء صلاحية (
exp
) الرمز المميّز للمعرّف. - إذا كنت بحاجة إلى التحقق من أنّ الرمز المميّز لرقم التعريف يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك مراجعة مطالبة
hd
التي تشير إلى النطاق المستضاف للمستخدم. ويجب استخدام هذه الطريقة عند تقييد الوصول إلى مورد معيّن على أعضاء نطاقات معيّنة فقط. في حال عدم تقديم هذا الادّعاء، يشير إلى أنّ الحساب لا ينتمي إلى نطاق تستضيفه Google.
بدلاً من كتابة الرمز الخاص بك لتنفيذ خطوات إثبات الملكية هذه، ننصحك بشدة باستخدام مكتبة عميل Google API للنظام الأساسي الذي تستخدمه أو مكتبة JWT للأغراض العامة. لأغراض التطوير وتصحيح الأخطاء، يمكنك استدعاء نقطة نهاية التحقّق من صحة tokeninfo
.
استخدام مكتبة برامج Google API
باستخدام إحدى مكتبات عملاء Google API (على سبيل المثال، Java وNode.js وPHP وPython) هي الطريقة الموصى بها للتحقق من صحة رموز Google ID المميزة في بيئة الإنتاج.
للتحقّق من صحة الرمز المميّز للمعرّف في لغة Java، استخدِم الكائن GoogleIdTokenVerifier. مثال:
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; ... GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory) // Specify the CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3)) .build(); // (Receive idTokenString by HTTPS POST) GoogleIdToken idToken = verifier.verify(idTokenString); if (idToken != null) { Payload payload = idToken.getPayload(); // Print user identifier String userId = payload.getSubject(); System.out.println("User ID: " + userId); // Get profile information from payload String email = payload.getEmail(); boolean emailVerified = Boolean.valueOf(payload.getEmailVerified()); String name = (String) payload.get("name"); String pictureUrl = (String) payload.get("picture"); String locale = (String) payload.get("locale"); String familyName = (String) payload.get("family_name"); String givenName = (String) payload.get("given_name"); // Use or store profile information // ... } else { System.out.println("Invalid ID token."); }
يتم استخدام طريقة GoogleIdTokenVerifier.verify()
للتحقّق من توقيع JWT ومطالبة aud
ومطالبة iss
وexp
.
إذا كنت بحاجة إلى التحقق من أنّ الرمز المميّز لرقم التعريف يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك إثبات صحة المطالبة باستخدام hd
من خلال التحقّق من اسم النطاق
الذي تعرضه طريقة Payload.getHostedDomain()
. إنّ نطاق المطالبة email
غير كافٍ لضمان إدارة الحساب من خلال نطاق أو مؤسسة.
للتحقّق من رمز مميّز للمعرّف في Node.js، استخدم Google Auth Library لـ Node.js. تثبيت المكتبة:
npm install google-auth-library --saveبعد ذلك، يمكنك استدعاء الدالة
verifyIdToken()
. مثال:
const {OAuth2Client} = require('google-auth-library'); const client = new OAuth2Client(); async function verify() { const ticket = await client.verifyIdToken({ idToken: token, audience: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3] }); const payload = ticket.getPayload(); const userid = payload['sub']; // If request specified a G Suite domain: // const domain = payload['hd']; } verify().catch(console.error);
تتحقّق الدالة verifyIdToken
من توقيع JWT ومطالبة aud
ومطالبة exp
وiss
.
إذا كنت بحاجة إلى التحقق من أنّ الرمز المميّز لرقم التعريف يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك مراجعة مطالبة hd
التي تشير إلى النطاق المستضاف للمستخدم. ويجب استخدام هذه الطريقة عند تقييد الوصول إلى مورد معيّن على أعضاء
نطاقات معيّنة فقط. في حال عدم تقديم هذا الادّعاء، يشير إلى أنّ الحساب لا ينتمي إلى
نطاق تستضيفه Google.
للتحقّق من صحة رمز مميّز لرقم التعريف في لغة PHP، يمكنك استخدام مكتبة برامج Google API للغة PHP. ثبِّت المكتبة (على سبيل المثال، باستخدام Composer):
composer require google/apiclientبعد ذلك، استدعِ الدالة
verifyIdToken()
. مثال:
require_once 'vendor/autoload.php'; // Get $id_token via HTTPS POST. $client = new Google_Client(['client_id' => $CLIENT_ID]); // Specify the CLIENT_ID of the app that accesses the backend $payload = $client->verifyIdToken($id_token); if ($payload) { $userid = $payload['sub']; // If request specified a G Suite domain: //$domain = $payload['hd']; } else { // Invalid ID token }
تتحقّق الدالة verifyIdToken
من توقيع JWT ومطالبة aud
ومطالبة exp
وiss
.
إذا كنت بحاجة إلى التحقق من أنّ الرمز المميّز لرقم التعريف يمثّل حساب مؤسسة على Google Workspace أو Cloud، يمكنك مراجعة مطالبة hd
التي تشير إلى النطاق المستضاف للمستخدم. ويجب استخدام هذه الطريقة عند تقييد الوصول إلى مورد معيّن على أعضاء
نطاقات معيّنة فقط. في حال عدم تقديم هذا الادّعاء، يشير إلى أنّ الحساب لا ينتمي إلى
نطاق تستضيفه Google.
للتحقق من الرمز المميز للمعرّف في بايثون، يمكنك استخدام الدالة verify_oauth2_token. مثال:
from google.oauth2 import id_token from google.auth.transport import requests # (Receive token by HTTPS POST) # ... try: # Specify the CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3]: # raise ValueError('Could not verify audience.') # If auth request is from a G Suite domain: # if idinfo['hd'] != GSUITE_DOMAIN_NAME: # raise ValueError('Wrong hosted domain.') # ID token is valid. Get the user's Google Account ID from the decoded token. userid = idinfo['sub'] except ValueError: # Invalid token pass
تتحقّق الدالة verify_oauth2_token
من توقيع JWT
ومطالبة aud
ومطالبة exp
.
يجب أيضًا إثبات صحة المطالبة hd
(إذا كان ذلك منطبقًا) من خلال فحص العنصر الذي
يعرضه verify_oauth2_token
. في حال وصول عدة برامج إلى
خادم الخلفية، أثبِت صحة مطالبة aud
يدويًا أيضًا.
جارٍ استدعاء نقطة نهاية iconinfo
تتوفّر طريقة سهلة للتحقّق من صحة توقيع الرمز المميّز للمعرّف من أجل تصحيح الأخطاء، وهي استخدام نقطة النهاية tokeninfo
. يشمل استدعاء نقطة النهاية هذه طلبًا إضافيًا للشبكة يؤدي إلى إجراء معظم عمليات التحقق نيابةً عنك أثناء اختبارك لعمليات التحقق من الصحة واستخراج الحمولات بطريقة صحيحة في الرمز الخاص بك. وهي غير مناسبة للاستخدام في الرموز البرمجية للإنتاج، لأنّه قد يتم تقييد الطلبات أو قد تحدث أخطاء متقطّعة بأي طريقة أخرى.
للتحقّق من صحة رمز مميّز للمعرّف باستخدام نقطة النهاية tokeninfo
، يمكنك تقديم طلب HTTPS
POST أو GET إلى نقطة النهاية، وإدخال الرمز المميّز للمعرّف في
معلَمة id_token
.
على سبيل المثال، للتحقق من الرمز المميز "XYZ123"، قم بإجراء طلب GET التالي:
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
إذا تم توقيع الرمز المميّز بشكل صحيح وكانت مطالبتا iss
وexp
تتضمّنان القيم المتوقّعة، ستتلقّى استجابة HTTP 200، حيث يحتوي النص على
مطالبات الرمز المميّز للمعرّف بتنسيق JSON.
إليك مثال على الرد:
{ // These six fields are included in all Google ID Tokens. "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", // These seven fields are only included when the user has granted the "profile" and // "email" OAuth scopes to the application. "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en" }
إذا كنت بحاجة إلى التأكّد من أنّ الرمز المميّز لرقم التعريف يمثّل حسابًا على Google Workspace، يمكنك التحقّق من
المطالبة hd
التي تشير إلى النطاق المستضاف للمستخدم. ويجب استخدام هذه الطريقة عند
حظر الوصول إلى مورد معيّن على أعضاء نطاقات معيّنة فقط. في حال عدم تقديم هذه المطالبة،
يشير ذلك إلى أنّ الحساب لا ينتمي إلى نطاق مستضاف على Google Workspace.
إنشاء حساب أو جلسة
بعد إثبات ملكية الرمز المميّز، تحقَّق مما إذا كان المستخدم مُدرجًا في قاعدة بيانات المستخدمين أم لا. إذا كان الأمر كذلك، أنشئ جلسة تمت مصادقتها للمستخدم. إذا لم يكن المستخدم بعد في قاعدة بيانات المستخدمين، أنشئ سجل مستخدم جديدًا من المعلومات المتوفرة في حمولة الرمز المميز للمعرّف، ثم أنشئ جلسة للمستخدم. يمكنك طلب من المستخدم تقديم أي معلومات إضافية مطلوبة في الملف الشخصي عند اكتشاف مستخدم تم إنشاؤه حديثًا في تطبيقك.
تأمين حسابات المستخدمين باستخدام ميزة "الحماية العابرة للحساب"
عند الاعتماد على Google لتسجيل دخول مستخدم، ستستفيد تلقائيًا من جميع ميزات الأمان والبنية الأساسية التي أنشأَتها Google لحماية بيانات المستخدم. ومع ذلك، في حال تم اختراق حساب المستخدم على Google أو كان هناك حدث أمني مهم آخر، وهو أمر مستبعد، يمكن أن يكون تطبيقك عرضةً أيضًا للهجوم. لحماية حساباتك بشكل أفضل من أي أحداث أمنية كبيرة، يمكنك استخدام ميزة الحماية العابرة للحساب لتلقّي تنبيهات الأمان من Google. عند تلقّي هذه الأحداث، ستحصل على إذن الوصول إلى التغييرات المهمة التي تطرأ على أمان حساب المستخدم على Google، ويمكنك بعدها اتخاذ إجراء بشأن خدمتك لتأمين حساباتك.