عملية ربط مبسطة باستخدام OAuth و"تسجيل الدخول باستخدام حساب Google"

نظرة عامة

تضيف ميزة الربط المبسّط المستند إلى OAuth في "تسجيل الدخول باستخدام حساب Google" خيار "تسجيل الدخول باستخدام حساب Google" إلى الربط المستند إلى OAuth. يوفّر ذلك تجربة ربط سلسة لمستخدمي Google، كما يتيح إنشاء حساب، ما يسمح للمستخدم بإنشاء حساب جديد على خدمتك باستخدام حساب Google.

لربط الحساب باستخدام OAuth و"تسجيل الدخول باستخدام حساب Google"، اتّبِع الخطوات العامة التالية:

  1. أولاً، اطلب من المستخدم الموافقة على الوصول إلى ملفه الشخصي في حساب Google.
  2. استخدِم المعلومات الواردة في ملفه الشخصي للتحقّق مما إذا كان حساب المستخدم متوفّرًا.
  3. بالنسبة إلى المستخدمين الحاليين، اربط الحسابات.
  4. إذا لم تتمكّن من العثور على مستخدم Google مطابق في نظام المصادقة، عليك التحقّق من صحة الرمز المميّز المعرّف الذي تلقّيته من Google. يمكنك بعد ذلك إنشاء مستخدم استنادًا إلى معلومات الملف الشخصي الواردة في رمز المعرّف المميّز.
تعرض هذه الصورة الخطوات التي يتّبعها المستخدم لربط حسابه على Google باستخدام عملية الربط المبسّطة. تعرض لقطة الشاشة الأولى كيف يمكن للمستخدم اختيار تطبيقك لربطه. تتيح لقطة الشاشة الثانية للمستخدم تأكيد ما إذا كان لديه حساب حالي على خدمتك أم لا. تتيح لقطة الشاشة الثالثة للمستخدم اختيار حساب Google الذي يريد ربطه. تعرض لقطة الشاشة الرابعة تأكيدًا لربط حساب المستخدم على Google بتطبيقك. وتعرض لقطة الشاشة الخامسة حساب مستخدم تم ربطه بنجاح في تطبيق Google.

الشكل 1 ربط الحسابات على هاتف المستخدم باستخدام ميزة "الربط السلس"

متطلبات ميزة "الربط السلس"

تنفيذ خادم OAuth

يجب أن تتوافق نقطة نهاية تبادل الرموز المميزة مع الأهداف check وcreate وget. اتّبِع الخطوات التالية لإكمال عملية ربط الحساب والتعرّف على الحالات التي يتم فيها استخدام النوايا المختلفة:

  1. هل لدى المستخدم حساب في نظام المصادقة؟ (يقرّر المستخدم ذلك من خلال اختيار "نعم" أو "لا")
    1. نعم : هل يستخدم المستخدم عنوان البريد الإلكتروني المرتبط بحساب Google لتسجيل الدخول إلى منصتك؟ (يقرّر المستخدم ذلك من خلال اختيار "نعم" أو "لا")
      1. نعم : هل لدى المستخدم حساب مطابق في نظام المصادقة؟ (يتم الاتصال بالرقم check intent للتأكيد)
        1. نعم : يتم الاتصال بـ get intent ويتم ربط الحساب إذا تم عرض نتيجة get intent بنجاح.
        2. لا : إنشاء حساب جديد؟ (يقرّر المستخدم ذلك من خلال اختيار "نعم" أو "لا")
          1. نعم : يتمّ استدعاء create intent ويتمّ ربط الحساب إذا تمّ عرض نتيجة إنشاء الغرض بنجاح.
          2. لا : يتم تفعيل عملية Web OAuth، ويتم توجيه المستخدم إلى المتصفّح، ويُمنح المستخدم خيار الربط بعنوان بريد إلكتروني مختلف.
      2. لا : يتم تفعيل مسار OAuth على الويب، ويتم توجيه المستخدم إلى المتصفّح، ويُمنح المستخدم خيار الربط بعنوان بريد إلكتروني مختلف.
    2. لا : هل لدى المستخدم حساب مطابق في نظام المصادقة؟ (يتم الاتصال بالرقم check intent للتأكيد)
      1. نعم : يتم الاتصال بـ get intent ويتم ربط الحساب إذا تم عرض نتيجة get intent بنجاح.
      2. يتم استدعاء NO : create intent ويتم ربط الحساب إذا تم عرض نتيجة إنشاء الغرض بنجاح.

检查现有用户账号(检查 intent)

在用户同意访问其 Google 个人资料后,Google 会发送 请求,其中包含 Google 用户身份的已签名断言。通过 断言包含的信息包括用户的 Google 账号 ID、 姓名和电子邮件地址为您的 Google Cloud 控制台配置的令牌交换端点 项目处理该请求。

如果您的身份验证中已有相应的 Google 账号 系统时,您的令牌交换端点会返回 account_found=true。如果 Google 账号与现有用户不匹配,您的令牌交换端点 返回“HTTP 404 Not Found”错误以及 account_found=false

请求的格式如下:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=check&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 check
grant_type 所交换的令牌的类型。对于这类请求 参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion 一个 JSON Web 令牌 (JWT),提供 Google 用户身份。JWT 包含的信息包括用户 Google 账号 ID、姓名和电子邮件地址。
client_id 您分配给 Google 的客户 ID。
client_secret 您分配给 Google 的客户端密钥。

如需响应 check intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证和解码 JWT 断言。
  • 检查您的身份验证系统中是否已存在该 Google 账号。
验证和解码 JWT 断言

您可以使用 适用于您所用语言的 JWT 解码库。使用 Google 的公钥,在 JWKPEM 格式,用于验证 令牌的签名。

解码后,JWT 断言如以下示例所示:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了验证令牌的签名之外,还要验证断言的 颁发者(iss 字段)为 https://accounts.google.com, (aud 字段)是分配给您的客户端 ID,并且令牌未过期 (exp 字段)。

使用 emailemail_verifiedhd 字段,您可以确定 Google 负责托管电子邮件地址,并对其具有权威性。如果 Google 权威性 - 用户当前被认定为合法账号所有者 您可以跳过密码或其他验证方法。否则,这些方法 可用于在关联之前验证账号。

Google 具有权威性的情形:

  • email 的后缀为 @gmail.com,这是一个 Gmail 账号。
  • email_verified 为 true 且 hd 已设置,这是 G Suite 账号。

用户无需使用 Gmail 或 G Suite 即可注册 Google 账号。时间 email 不包含 @gmail.com 后缀,且 hd 不存在 Google 不 建议使用权威凭据和密码或其他验证方法进行验证 用户。email_verified 可能为 true,因为 Google 最初验证了 创建 Google 账号后,该用户会获得第三方的所有权, 后,电子邮件账号可能已更改。

检查您的身份验证系统中是否已存在该 Google 账号

请检查以下任一条件是否成立:

  • Google 账号 ID(可在断言的 sub 字段中找到)位于您的用户中 数据库。
  • 断言中的电子邮件地址与用户数据库中的用户匹配。

如果满足上述任一条件,则表明用户已注册。在这种情况下 返回如下所示的响应:

HTTP/1.1 200 Success
Content-Type: application/json;charset=UTF-8

{
  "account_found":"true",
}

如果 Google 账号 ID 和 断言与您的数据库中的用户匹配,该用户尚未注册。在 在这种情况下,您的令牌交换端点需要返回 HTTP 404 错误 指定 "account_found": "false",如以下示例所示:

HTTP/1.1 404 Not found
Content-Type: application/json;charset=UTF-8

{
  "account_found":"false",
}

التعامل مع الربط التلقائي (تحقيق النية)

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

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

يكون الطلب بالشكل التالي:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=get&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

يجب أن تتمكّن نقطة نهاية تبادل الرموز المميّزة من معالجة المَعلمات التالية:

مَعلمات نقطة نهاية الرمز المميّز
intent بالنسبة إلى هذه الطلبات، تكون قيمة هذه المَعلمة هي get.
grant_type تمثّل هذه السمة نوع الرمز المميّز الذي يتم تبادله. بالنسبة لهذه الطلبات، سيتم المعلَمة urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion يشير هذا المصطلح إلى رمز JSON المميّز للويب (JWT) ويقدِّم تأكيدًا موقَّعًا على بيانات وهوية المستخدم. يحتوي JWT على معلومات تتضمن عنوان URL الخاص رقم تعريف حساب Google والاسم وعنوان البريد الإلكتروني
scope اختياري: أي نطاقات تم ضبط Google فيها للطلب منها المستخدمين.
client_id معرِّف العميل الذي عيّنته لـ Google.
client_secret سر العميل الذي خصّصته لـ Google.

للردّ على طلبات intent لـ get، يجب أن تنفِّذ نقطة نهاية تبادل الرموز المميّزة الخطوات التالية:

  • التحقق من صحة تأكيد JWT وفك ترميزه
  • تحقَّق مما إذا كان حساب Google متوفّرًا من قبل في نظام المصادقة.
验证和解码 JWT 断言

您可以使用 适用于您所用语言的 JWT 解码库。使用 Google 的公钥,在 JWKPEM 格式,用于验证 令牌的签名。

解码后,JWT 断言如以下示例所示:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了验证令牌的签名之外,还要验证断言的 颁发者(iss 字段)为 https://accounts.google.com, (aud 字段)是分配给您的客户端 ID,并且令牌未过期 (exp 字段)。

使用 emailemail_verifiedhd 字段,您可以确定 Google 负责托管电子邮件地址,并对其具有权威性。如果 Google 权威性 - 用户当前被认定为合法账号所有者 您可以跳过密码或其他验证方法。否则,这些方法 可用于在关联之前验证账号。

Google 具有权威性的情形:

  • email 的后缀为 @gmail.com,这是一个 Gmail 账号。
  • email_verified 为 true 且 hd 已设置,这是 G Suite 账号。

用户无需使用 Gmail 或 G Suite 即可注册 Google 账号。时间 email 不包含 @gmail.com 后缀,且 hd 不存在 Google 不 建议使用权威凭据和密码或其他验证方法进行验证 用户。email_verified 可能为 true,因为 Google 最初验证了 创建 Google 账号后,该用户会获得第三方的所有权, 后,电子邮件账号可能已更改。

التأكّد من توفّر حساب Google في نظام المصادقة

تحقق مما إذا كان أي من الشروط التالية صحيحًا:

  • رقم تعريف حساب Google، الوارد في حقل sub في التأكيد، موجود في حساب المستخدم. قاعدة البيانات.
  • يتطابق عنوان البريد الإلكتروني الوارد في التأكيد مع مستخدم في قاعدة بيانات المستخدم الخاصة بك.

في حال العثور على حساب للمستخدم، عليك إصدار رمز دخول وعرض القيم في كائن JSON في نص استجابة HTTPS، كما في المثال التالي:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": SECONDS_TO_EXPIRATION
}

في بعض الحالات، قد يتعذّر على المستخدم ربط الحساب استنادًا إلى الرمز المميّز للمعرّف. إذا كان لأي سبب من الأسباب، تحتاج نقطة نهاية تبادل الرمز المميز إلى الرد باستخدام HTTP 401 يحدد الخطأ error=linking_error، كما يبيِّن المثال التالي:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

عندما تتلقّى Google ردًّا بالخطأ 401 مع linking_error، ترسل Google المستخدِم إلى نقطة نهاية التفويض مع استخدام login_hint كمَعلمة. تشير رسالة الأشكال البيانية إكمال المستخدم لربط الحساب باستخدام مسار ربط OAuth في المتصفِّح

使用“使用 Google 账号登录”处理账号创建(创建 intent)

当用户需要在您的服务中创建账号时,Google 会向您的令牌交换端点发出请求,其中指定了 intent=create

该请求采用以下形式:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

response_type=token&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&scope=SCOPES&intent=create&assertion=JWT&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 create
grant_type 要交换的令牌的类型。对于这些请求,此 参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion JSON 网络令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含的信息包括用户的 Google 账号 ID、姓名和电子邮件地址。
client_id 您分配给 Google 的客户端 ID。
client_secret 您分配给 Google 的客户端密钥。

assertion 参数中的 JWT 包含用户的 Google 账号 ID、姓名和电子邮件地址,您可以使用这些信息在您的服务中创建新账号。

如需响应 create intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证 JWT 断言并对其进行解码。
  • 验证用户信息并创建新账号。
验证和解码 JWT 断言

您可以使用 适用于您所用语言的 JWT 解码库。使用 Google 的公钥,在 JWKPEM 格式,用于验证 令牌的签名。

解码后,JWT 断言如以下示例所示:

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

除了验证令牌的签名之外,还要验证断言的 颁发者(iss 字段)为 https://accounts.google.com, (aud 字段)是分配给您的客户端 ID,并且令牌未过期 (exp 字段)。

使用 emailemail_verifiedhd 字段,您可以确定 Google 负责托管电子邮件地址,并对其具有权威性。如果 Google 权威性 - 用户当前被认定为合法账号所有者 您可以跳过密码或其他验证方法。否则,这些方法 可用于在关联之前验证账号。

Google 具有权威性的情形:

  • email 的后缀为 @gmail.com,这是一个 Gmail 账号。
  • email_verified 为 true 且 hd 已设置,这是 G Suite 账号。

用户无需使用 Gmail 或 G Suite 即可注册 Google 账号。时间 email 不包含 @gmail.com 后缀,且 hd 不存在 Google 不 建议使用权威凭据和密码或其他验证方法进行验证 用户。email_verified 可能为 true,因为 Google 最初验证了 创建 Google 账号后,该用户会获得第三方的所有权, 后,电子邮件账号可能已更改。

验证用户信息并创建新账号

检查是否满足以下任一条件:

  • 断言的 sub 字段中找到的 Google 账号 ID 位于您的用户数据库中。
  • 断言中的电子邮件地址与用户数据库中的用户匹配。

如果满足任一条件,请提示用户将其现有账号与其 Google 账号相关联。为此,请使用 HTTP 401 错误响应请求,该错误指定了 error=linking_error 并将用户的电子邮件地址作为 login_hint。以下是示例响应:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

当 Google 收到包含 linking_error 的 401 错误响应时,Google 会将用户发送到您的授权端点,并将 login_hint 作为参数。用户在其浏览器中使用 OAuth 关联流程完成账号关联。

如果这两个条件都不满足,请使用 JWT 中提供的信息创建新的用户账号。新账号通常没有设置密码。建议您将“使用 Google 账号登录”添加到其他平台,以便用户可以在应用的所有界面上使用 Google 账号登录。或者,您也可以通过电子邮件向用户发送一个链接,该链接会启动密码恢复流程,让用户设置密码以便在其他平台上登录。

创建完成后,请发出访问令牌 和刷新令牌 ,并在 HTTPS 响应正文中的 JSON 对象内返回这些值,如以下示例所示:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": SECONDS_TO_EXPIRATION
}

الحصول على معرّف عميل Google API

سيُطلب منك تقديم معرّف عميل Google API أثناء عملية التسجيل لربط الحساب.

للحصول على معرّف عميل واجهة برمجة التطبيقات باستخدام المشروع الذي أنشأته أثناء إكمال خطوات ربط حساب OAuth لإجراء ذلك، يُرجى إكمال الخطوات التالية:

  1. انتقِل إلى صفحة العملاء.
  2. أنشئ مشروعًا على Google APIs أو اختَر مشروعًا حاليًا.

    إذا لم يكن مشروعك يتضمّن معرّف عميل من نوع تطبيق الويب، انقر على إنشاء عميل لإنشاء معرّف. احرص على تضمين نطاق موقعك الإلكتروني في مربّع مصادر JavaScript المسموح بها. عند إجراء اختبارات أو عمليات تطوير محلية، يجب إضافة كل من http://localhost وhttp://localhost:<port_number> إلى حقل مصادر JavaScript المعتمَدة.

التحقّق من صحة عملية التنفيذ

يمكنك التحقّق من صحة التنفيذ باستخدام أداة مساحة بروتوكول OAuth 2.0.

في الأداة، اتّبِع الخطوات التالية:

  1. انقر على الإعداد لفتح نافذة "إعدادات OAuth 2.0".
  2. في حقل مسار OAuth، اختَر من جهة العميل.
  3. في حقل نقاط نهاية OAuth، اختَر مخصّص.
  4. حدِّد نقطة نهاية OAuth 2.0 ومعرّف العميل الذي خصّصته لـ Google في الحقلَين المناسبَين.
  5. في قسم الخطوة 1، لا تحدّد أي نطاقات Google. بدلاً من ذلك، اترك هذا الحقل فارغًا أو اكتب نطاقًا صالحًا لخادمك (أو سلسلة عشوائية إذا كنت لا تستخدم نطاقات OAuth). عند الانتهاء، انقر على تفويض واجهات برمجة التطبيقات.
  6. في القسمَين الخطوة 2 والخطوة 3، اتّبِع مسار OAuth 2.0 وتأكَّد من أنّ كل خطوة تعمل على النحو المطلوب.

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

في الأداة، اتّبِع الخطوات التالية:

  1. انقر على الزر تسجيل الدخول باستخدام حساب Google.
  2. اختَر الحساب الذي تريد ربطه.
  3. أدخِل رقم تعريف الخدمة.
  4. يمكنك اختياريًا إدخال نطاق واحد أو أكثر ستطلب الوصول إليه.
  5. انقر على بدء العرض التوضيحي.
  6. أكِّد أنّه يمكنك الموافقة على طلب ربط الحساب ورفضه عندما يُطلب منك ذلك.
  7. تأكَّد من إعادة توجيهك إلى منصتك.