Autenticarse con un servidor backend

Si utiliza el inicio de sesión de Google con una aplicación o un sitio que se comunica con un servidor backend, es posible que deba identificar al usuario que ha iniciado sesión actualmente en el servidor. Para hacerlo de forma segura, después de que un usuario inicie sesión correctamente, envíe el token de identificación del usuario a su servidor mediante HTTPS. Luego, en el servidor, verifique la integridad del token de ID y use la información del usuario contenida en el token para establecer una sesión o crear una nueva cuenta.

Envíe el token de identificación a su servidor

Después de que un usuario inicie sesión correctamente, obtenga el token de identificación del usuario:

- (void)signIn:(GIDSignIn *)signIn
    didSignInForUser:(GIDGoogleUser *)user
           withError:(NSError *)error {
  NSString *idToken = user.authentication.idToken;
  ...
}

Luego, envíe el token de ID a su servidor con una solicitud HTTPS POST:

NSString *signinEndpoint = @"https://yourbackend.example.com/tokensignin";
NSDictionary *params = @{@"idtoken": idToken};

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:signinEndpoint];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:[self httpBodyForParamsDictionary:params]];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request
                                   queue:queue
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                         if (error) {
                           NSLog(@"Error: %@", error.localizedDescription);
                         } else {
                           NSLog(@"Signed in as %@", data.bytes);
                         }
                       }];

Verificar la integridad del token de identificación

Después de recibir el token de ID por HTTPS POST, debe verificar la integridad del token. Para verificar que el token es válido, asegúrese de que se cumplan los siguientes criterios:

  • El token de identificación está debidamente firmado por Google. Utilice las claves públicas de Google (disponibles en formato JWK o PEM ) para verificar la firma del token. Estas claves se rotan regularmente; examine el encabezado Cache-Control en la respuesta para determinar cuándo debe recuperarlos nuevamente.
  • El valor de aud en el token de ID es igual a uno de los ID de cliente de su aplicación. Esta verificación es necesaria para evitar que los tokens de identificación emitidos a una aplicación malintencionada se utilicen para acceder a datos sobre el mismo usuario en el servidor backend de su aplicación.
  • El valor de iss en el token de identificación es igual a accounts.google.com o https://accounts.google.com .
  • El tiempo de caducidad ( exp ) del token de ID no ha pasado.
  • Si desea restringir el acceso solo a los miembros de su dominio de G Suite, verifique que el token de ID tenga un reclamo hd que coincida con su nombre de dominio de G Suite.

En lugar de escribir su propio código para realizar estos pasos de verificación, recomendamos encarecidamente utilizar una biblioteca cliente de API de Google para su plataforma o una biblioteca JWT de uso general. Para el desarrollo y la depuración, puede llamar a nuestro tokeninfo final de validación de tokeninfo .

Uso de una biblioteca cliente de API de Google

El uso de una de las bibliotecas cliente de la API de Google (p. Ej., Java , Node.js , PHP , Python ) es la forma recomendada de validar los tokens de ID de Google en un entorno de producción.

Java

Para validar un token de ID en Java, use el objeto GoogleIdTokenVerifier . Por ejemplo:

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.");
}

El método GoogleIdTokenVerifier.verify() verifica la firma JWT, el reclamo aud , el reclamo iss y el reclamo exp .

Si desea restringir el acceso solo a los miembros de su dominio de G Suite, también verifique el reclamo hd al verificar el nombre de dominio devuelto por el método Payload.getHostedDomain() .

Node.js

Para validar un token de ID en Node.js, use la biblioteca de autenticación de Google para Node.js. Instale la biblioteca:

npm install google-auth-library --save
Luego, llame a la función verifyIdToken() . Por ejemplo:

const {OAuth2Client} = require('google-auth-library');
const client = new OAuth2Client(CLIENT_ID);
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);

La función verifyIdToken verifica la firma JWT, el reclamo aud , el reclamo exp y el reclamo iss .

Si desea restringir el acceso solo a los miembros de su dominio de G Suite, también verifique que el reclamo de hd coincida con su nombre de dominio de G Suite.

PHP

Para validar un token de ID en PHP, utilice la biblioteca cliente de la API de Google para PHP . Instale la biblioteca (por ejemplo, usando Composer):

composer require google/apiclient
Luego, llame a la función verifyIdToken() . Por ejemplo:

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
}

La función verifyIdToken verifica la firma JWT, el reclamo aud , el reclamo exp y el reclamo iss .

Si desea restringir el acceso solo a los miembros de su dominio de G Suite, también verifique que el reclamo hd coincida con su nombre de dominio de G Suite.

Pitón

Para validar un token de ID en Python, use la función verify_oauth2_token . Por ejemplo:

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

La función verify_oauth2_token verifica la firma JWT, el reclamo aud y el reclamo exp . También debe verificar el reclamo hd (si corresponde) examinando el objeto que verify_oauth2_token devuelve. Si varios clientes acceden al servidor backend, también verifique manualmente la reclamación aud .

Llamar al punto final de tokeninfo

Una forma sencilla de validar la firma de un token de ID para la depuración es utilizar el tokeninfo final de tokeninfo . Llamar a este punto final implica una solicitud de red adicional que realiza la mayor parte de la validación por usted mientras prueba la validación adecuada y la extracción de carga útil en su propio código. No es adecuado para su uso en código de producción, ya que las solicitudes pueden verse limitadas o sujetas a errores intermitentes.

Para validar un token de ID utilizando el tokeninfo final de tokeninfo , realice una solicitud HTTPS POST o GET al punto final y pase su token de ID en el parámetro id_token . Por ejemplo, para validar el token "XYZ123", realice la siguiente solicitud GET:

https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123

Si el token está firmado correctamente y las reclamaciones iss y exp tienen los valores esperados, obtendrá una respuesta HTTP 200, donde el cuerpo contiene las reclamaciones del token de ID con formato JSON. Aquí hay una respuesta de ejemplo:

{
 // 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"
}

Si es cliente de G Suite, es posible que también le interese el reclamo hd , que indica el dominio alojado del usuario. Esto se puede usar para restringir el acceso a un recurso solo a miembros de ciertos dominios. La ausencia de esta afirmación indica que el usuario no pertenece a un dominio alojado en G Suite.

Crea una cuenta o sesión

Una vez que haya verificado el token, compruebe si el usuario ya está en su base de datos de usuarios. Si es así, establezca una sesión autenticada para el usuario. Si el usuario aún no está en su base de datos de usuarios, cree un nuevo registro de usuario a partir de la información en la carga útil del token de ID y establezca una sesión para el usuario. Puede solicitar al usuario cualquier información de perfil adicional que necesite cuando detecte un usuario recién creado en su aplicación.

Asegurar las cuentas de sus usuarios con protección de cuentas cruzadas

Cuando confía en Google para iniciar sesión con un usuario, se beneficiará automáticamente de todas las funciones de seguridad y la infraestructura que Google ha creado para proteger los datos del usuario. Sin embargo, en el improbable caso de que la cuenta de Google del usuario se vea comprometida o se produzca algún otro evento de seguridad importante, su aplicación también puede ser vulnerable a un ataque. Para proteger mejor sus cuentas de cualquier evento de seguridad importante, use Protección de cuentas cruzadas para recibir alertas de seguridad de Google. Cuando recibe estos eventos, obtiene visibilidad de los cambios importantes en la seguridad de la cuenta de Google del usuario y luego puede tomar medidas en su servicio para proteger sus cuentas.