يسترد برنامج تسجيل الدخول لميزة "نقرة واحدة" الرمز المميّز لمعرّف Google عندما يختار المستخدم حسابًا على Google. الرمز المميز للمعرف هو تأكيد موقّع لهوية المستخدم يحتوي أيضًا على معلومات الملف الشخصي الأساسية للمستخدم، وقد يتضمن عنوان البريد الإلكتروني الذي تحققت منه Google.
عند توفّر رموز التعريف المميَّزة، يمكنك استخدامها للمصادقة بأمان مع الخلفية الخاصة بتطبيقك، أو اشتراك المستخدم تلقائيًا في حساب جديد بدون الحاجة إلى إثبات ملكية عنوان البريد الإلكتروني للمستخدم.
لتسجيل الدخول أو اشتراك مستخدم باستخدام الرمز المميز للمعرّف، أرسِل الرمز المميز إلى الخلفية الخلفية لتطبيقك. في الخلفية، تحقَّق من الرمز المميّز باستخدام مكتبة برامج واجهة Google API أو مكتبة JWT للأغراض العامة. إذا لم يسجّل المستخدم الدخول إلى تطبيقك باستخدام حساب Google هذا من قبل، أنشئ حسابًا جديدًا.
إذا اخترت بشكل اختياري استخدام رقم غير مميّز للمساعدة في تجنّب هجمات إعادة التشغيل، استخدِم getNonce لإرساله مع الرمز المميّز للمعرّف إلى خادم الخلفية، وتحقق من القيمة المتوقّعة. ننصحك بشدّة باستخدام نص لنا لتحسين سلامة المستخدم وأمانه.
الحصول على رمز مميز للمعرّف من كائن بيانات الاعتماد
بعد استرداد بيانات اعتماد مستخدم، تحقق مما إذا كان كائن بيانات الاعتماد يشتمل على رمز مميز للمعرف. إذا كان الأمر كذلك، فأرسله إلى الخلفية.
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.
باستخدام الحقول email
وemail_verified
وhd
، يمكنك تحديد ما إذا كان
تستضيف Google عنوان بريد إلكتروني وموثوقًا به. في الحالات التي تكون فيها Google موثوقة،
يكون المستخدم معروفًا كمالك الحساب الشرعي، ويمكنك تخطي كلمة المرور أو
طرق التحدي.
الحالات التي تكون فيها Google موثوقة:
- السمة
email
هي اللاحقة@gmail.com
، وهذا حساب Gmail. email_verified
صحيح وتم ضبطhd
، هذا حساب G Suite.
يمكن للمستخدمين التسجيل للحصول على حسابات Google بدون استخدام Gmail أو G Suite. فعندما
لا يحتوي email
على اللاحقة @gmail.com
وhd
غير موجود، كما أن Google لا
موثوقة وكلمة المرور أو طرق التحقق الأخرى للتحقق
المستخدم. يمكن أن يكون email_verified
صحيحًا أيضًا لأن Google تحققت في البداية من صحة
المستخدم عند إنشاء حساب 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 the request specified a Google Workspace 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 the request specified a Google Workspace 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 the request specified a Google Workspace domain # if idinfo['hd'] != DOMAIN_NAME: # raise ValueError('Wrong domain name.') # 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، ويمكنك بعد ذلك اتخاذ إجراء بشأن خدمتك لتأمين حساباتك.