Vinculación optimizada con OAuth y Acceso con Google

Descripción general

La vinculación optimizada del Acceso con Google basado en OAuth agrega el Acceso con Google por encima de Vinculación de OAuth. Esto proporciona una experiencia de vinculación fluida para a los usuarios de Google y, además, habilita la creación de cuentas, que les permite crear una cuenta nueva en tu servicio con su Cuenta de Google.

Para vincular las cuentas con OAuth y el Acceso con Google, sigue estas indicaciones generales pasos:

  1. En primer lugar, solicita al usuario que dé su consentimiento para acceder a su perfil de Google.
  2. Usa la información de su perfil para comprobar si existe la cuenta de usuario.
  3. Para los usuarios existentes, vincula las cuentas.
  4. Si no encuentras una coincidencia para el usuario de Google en tu sistema de autenticación, validar el token de ID que se recibió de Google. Luego, puedes crear un usuario basado en en la información de perfil que se encuentra en el token de ID.
En esta figura, se muestran los pasos para que un usuario vincule su Cuenta de Google con el flujo de vinculación optimizado. La primera captura de pantalla muestra cómo un usuario puede seleccionar tu app para vincularla. La segunda captura de pantalla le permite al usuario confirmar si tiene una cuenta existente en tu servicio. La tercera captura de pantalla le permite al usuario seleccionar la Cuenta de Google con la que desea vincularse. La cuarta captura de pantalla muestra la confirmación para vincular su Cuenta de Google con tu app. En la quinta captura de pantalla, se muestra una cuenta de usuario vinculada correctamente en la app de Google.

Figura 1. Vinculación de cuentas en el teléfono de un usuario con la vinculación optimizada

Requisitos para una vinculación optimizada

Implementa tu servidor de OAuth

El extremo de intercambio de tokens debe admitir los intents check, create y get. A continuación, se muestran los pasos completados a través del flujo de vinculación de cuentas y se indica cuándo se llama a los diferentes intents:

  1. ¿El usuario tiene una cuenta en tu sistema de autenticación? (El usuario decide si selecciona SÍ o NO)
    1. SÍ: ¿El usuario usa el correo electrónico asociado a su Cuenta de Google para acceder a tu plataforma? (El usuario decide si selecciona SÍ o NO)
      1. SÍ: ¿El usuario tiene una cuenta que coincida en tu sistema de autenticación? (Se llama a check intent para confirmar).
        1. SÍ : Se llama a get intent y se vincula la cuenta si se muestra correctamente el intent GET.
        2. NO, ¿crear una cuenta nueva? (El usuario decide si selecciona SÍ o NO)
          1. SÍ : Si se muestra correctamente el intent de creación, se llama a create intent y se vincula la cuenta.
          2. NO : Se activa el flujo de OAuth web, se dirige al usuario a su navegador y el usuario tiene la opción de vincularse con un correo electrónico diferente.
      2. NO : Se activa el flujo de OAuth web, se dirige al usuario a su navegador y se le ofrece la opción de vincular con un correo electrónico diferente.
    2. NO: ¿El usuario tiene una cuenta que coincida en tu sistema de autenticación? (Se llama a check intent para confirmar).
      1. SÍ : Se llama a get intent y se vincula la cuenta si se muestra correctamente el intent GET.
      2. NO : Se llama a create intent y se vincula la cuenta si se muestra correctamente el intent de creación.

检查现有用户账号(检查 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",
}

Cómo controlar la vinculación automática (obtener intent)

Una vez que el usuario da su consentimiento para acceder a su perfil de Google, Google envía un solicitud que incluya una aserción firmada de la identidad del usuario de Google. El contiene información que incluye el ID de la Cuenta de Google del usuario, y tu dirección de correo electrónico. El extremo de intercambio de tokens configurado para tu el proyecto se encargará de esa solicitud.

Si la Cuenta de Google correspondiente ya está presente en tu autenticación tu extremo de intercambio de tokens devuelve un token al usuario. Si el botón La Cuenta de Google no coincide con un usuario existente, tu extremo de intercambio de token muestra un error linking_error y un login_hint opcional.

La solicitud tiene el siguiente formato:

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

El extremo de intercambio de tokens debe ser capaz de controlar los siguientes parámetros:

Parámetros de extremo del token
intent Para estas solicitudes, el valor de este parámetro es get.
grant_type El tipo de token que se intercambia. Para estas solicitudes, este tiene el valor urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion Un token web JSON (JWT) que proporciona una aserción firmada del token de Google la identidad del usuario. El JWT contiene información que incluye los datos ID, nombre y dirección de correo electrónico de la Cuenta de Google.
scope Opcional: Cualquier alcance que hayas configurado Google para que solicite solicitudes usuarios.
client_id El ID de cliente que le asignaste a Google
client_secret El secreto de cliente que asignaste a Google.

Para responder a las solicitudes de intent get, el extremo de intercambio de tokens debe realizar los siguientes pasos:

  • Valida y decodifica la aserción de JWT.
  • Verifica si la Cuenta de Google ya está presente en tu sistema de autenticación.
验证和解码 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 账号后,该用户会获得第三方的所有权, 后,电子邮件账号可能已更改。

Verifica si la Cuenta de Google ya está presente en tu sistema de autenticación

Verifica si se cumple alguna de las siguientes condiciones:

  • El ID de la Cuenta de Google, que se encuentra en el campo sub de la aserción, está en tu usuario en la base de datos.
  • La dirección de correo electrónico en la aserción coincide con un usuario de tu base de datos de usuarios.

Si se encuentra una cuenta para el usuario, emite un token de acceso y muestra los valores en un objeto JSON en el cuerpo de la respuesta HTTPS, como en el siguiente ejemplo:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",

  "refresh_token": "REFRESH_TOKEN",

  "expires_in": SECONDS_TO_EXPIRATION
}

En algunos casos, la vinculación de cuentas basada en un token de ID podría fallar para el usuario. Si lo hace por alguna razón, tu extremo de intercambio de token debe responder con un 401 que especifica error=linking_error, como se muestra en el siguiente ejemplo:

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

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

Cuando Google recibe una respuesta de error 401 con linking_error, Google envía al usuario al extremo de autorización con login_hint como parámetro. El El usuario completa la vinculación de la cuenta con el flujo de vinculación de OAuth en su navegador.

Controla la creación de cuentas mediante el Acceso con Google (crea un intent)

Cuando un usuario necesita crear una cuenta en tu servicio, Google realiza una solicitud. al extremo de intercambio de tokens que especifique intent=create.

La solicitud tiene el siguiente formato:

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

El extremo de intercambio de tokens debe poder controlar los siguientes parámetros:

Parámetros de extremo del token
intent Para estas solicitudes, el valor de este parámetro es create.
grant_type El tipo de token que se intercambia. Para estas solicitudes, este tiene el valor urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion Un token web JSON (JWT) que proporciona una aserción firmada del token de Google la identidad del usuario. El JWT contiene información que incluye los datos ID, nombre y dirección de correo electrónico de la Cuenta de Google.
client_id El ID de cliente que le asignaste a Google
client_secret El secreto de cliente que asignaste a Google.

El JWT dentro del parámetro assertion contiene el ID de la Cuenta de Google del usuario. y tu dirección de correo electrónico, que podrás usar para crear una cuenta nueva en tu servicio.

Para responder a las solicitudes de intent create, el extremo de intercambio de tokens debe realizar los siguientes pasos:

  • Valida y decodifica la aserción de JWT.
  • Valida la información del usuario y crea una cuenta nueva.
验证和解码 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 账号后,该用户会获得第三方的所有权, 后,电子邮件账号可能已更改。

Validar la información del usuario y crear una cuenta nueva

Verifica si se cumple alguna de las siguientes condiciones:

  • El ID de la Cuenta de Google, que se encuentra en el campo sub de la aserción, está en tu usuario en la base de datos.
  • La dirección de correo electrónico en la aserción coincide con un usuario de tu base de datos de usuarios.

Si se cumple alguna de estas condiciones, solicita al usuario que vincule su cuenta existente. con su Cuenta de Google. Para ello, responde la solicitud con un error HTTP 401 que especifique error=linking_error y proporcione la dirección de correo electrónico del usuario como el login_hint A continuación, se muestra una respuesta de ejemplo:

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

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

Cuando Google recibe una respuesta de error 401 con linking_error, Google envía al usuario al extremo de autorización con login_hint como parámetro. El El usuario completa la vinculación de la cuenta con el flujo de vinculación de OAuth en su navegador.

Si ninguna condición es verdadera, crea una nueva cuenta de usuario con la información. proporcionadas en el JWT. Las cuentas nuevas no suelen tener una contraseña establecida. Es se recomendó agregar Acceso con Google a otras plataformas para permitir que los usuarios acceda con Google en todas las plataformas de su aplicación. Como alternativa, puedes enviarle al usuario un vínculo que inicie el flujo de recuperación de la contraseña para configurar una contraseña para acceder en otras plataformas.

Cuando se complete la creación, emite un token de acceso un token de actualización y se mostrarán los valores de un objeto JSON en el cuerpo de la respuesta HTTPS, como en el siguiente ejemplo:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",

  "refresh_token": "REFRESH_TOKEN",

  "expires_in": SECONDS_TO_EXPIRATION
}

Obtén tu ID de cliente de la API de Google

Tendrá que proporcionar su ID de cliente de la API de Google durante el proceso de registro de la vinculación de cuentas.

Para obtener tu ID de cliente de API con el proyecto que creaste mientras completaste los pasos de la Vinculación con OAuth. Para ello, completa los siguientes pasos:

  1. Abre la página Credenciales de la Consola de APIs de Google.
  2. Crea o selecciona un proyecto de las APIs de Google.

    Si tu proyecto no tiene un ID de cliente para el tipo de aplicación web, haz clic en Crear credenciales > ID de cliente de OAuth para crear uno. Asegúrate de incluir el dominio de tu sitio en el cuadro Orígenes autorizados de JavaScript. Cuando realizas para pruebas o desarrollo locales, debes agregar http://localhost y http://localhost:<port_number> al campo Orígenes autorizados de JavaScript.

Cómo validar la implementación

Puedes validar tu implementación con la herramienta OAuth 2.0 Playground.

En la herramienta, sigue estos pasos:

  1. Haz clic en Configuración para abrir la ventana de configuración de OAuth 2.0.
  2. En el campo Flujo de OAuth, selecciona Del cliente.
  3. En el campo Extremos de OAuth, selecciona Personalizado.
  4. Especifica tu extremo de OAuth 2.0 y el ID de cliente que le asignaste a Google en los campos correspondientes.
  5. En la sección Paso 1, no selecciones ningún alcance de Google. En su lugar, deja este campo en blanco o escribe un alcance válido para tu servidor (o una cadena arbitraria si no usas permisos de OAuth). Cuando termines, haz clic en Autorizar APIs.
  6. En las secciones Paso 2 y Paso 3, revisa el flujo de OAuth 2.0 y verifica que cada paso funcione según lo previsto.

Puedes validar tu implementación con la herramienta de demostración de vinculación de Cuentas de Google.

En la herramienta, sigue estos pasos:

  1. Haz clic en el botón Acceder con Google.
  2. Elige la cuenta que quieres vincular.
  3. Ingresa el ID del servicio.
  4. De forma opcional, ingresa uno o más permisos para los que solicitarás acceso.
  5. Haz clic en Iniciar demostración.
  6. Cuando se te solicite, confirma que puedes dar tu consentimiento y rechazar la solicitud de vinculación.
  7. Confirma que se te redireccionó a tu plataforma.