> ## Documentation Index
> Fetch the complete documentation index at: https://documentation.onesignal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Verificación de identidad

> Previene la suplantación de usuarios requiriendo JWTs generados en el servidor para verificar IDs de Usuario Externos, correos electrónicos y suscripciones de SMS enviados a OneSignal.

## Descripción general

OneSignal ofrece una función de seguridad mejorada llamada Verificación de Identidad para ayudar a prevenir la suplantación de usuarios. Esta función utiliza JSON Web Tokens, o [JWTs](https://jwt.io/introduction), generados de forma segura en tu servidor. Para verificar la información de suscripción, estos tokens se pasan a tu aplicación y a la API de OneSignal.

Habilita la Verificación de Identidad para proteger:

* Iniciar sesión de usuarios
* Agregar suscripciones de correo electrónico
* Agregar suscripciones de SMS
* Modificar identidades de usuarios

<Warning>
  La Verificación de Identidad está actualmente en beta. Contacta a `support@onesignal.com` para habilitarla en tu cuenta. Una vez que el soporte la habilite, la activas en tu panel (ver [Paso 5](#enable-token-identity-verification-in-the-dashboard)).
</Warning>

## Requisitos previos

* Una aplicación OneSignal existente con una plataforma push configurada.

* Una aplicación móvil integrada con uno de los SDKs compatibles:

  * [OneSignal Android SDK 5.2.0+](https://github.com/OneSignal/OneSignal-Android-SDK/releases)
  * [OneSignal iOS SDK 5.3.0+](https://github.com/OneSignal/OneSignal-iOS-SDK/releases)

<Note>
  Soporte para wrapper SDK (Flutter, React Native, Unity, etc.) próximamente.
</Note>

## Configuración

<Steps>
  <Step title="Generar nuevas claves">
    Inicia sesión en tu cuenta de OneSignal y navega a **Configuración > Claves e IDs > Verificación de Identidad**.

    <Frame caption="Configuración de Verificación de Identidad">
      <img src="https://mintcdn.com/onesignal/Z6xkXGfmy814If53/images/docs/d6f1009-keys_and_ids.png?fit=max&auto=format&n=Z6xkXGfmy814If53&q=85&s=ffc30e4a1f08dcbe4e6a2e4935a7f5de" alt="Settings page showing Keys and IDs with Identity Verification section" width="2420" height="1614" data-path="images/docs/d6f1009-keys_and_ids.png" />
    </Frame>

    Haz clic en **Generar Nuevas Claves** para crear un nuevo par de claves.

    <Frame caption="Creación de nuevo par de claves">
      <img src="https://mintcdn.com/onesignal/56ctKxZSV4m5VEkn/images/docs/b24c1fd-Identity_Verification.png?fit=max&auto=format&n=56ctKxZSV4m5VEkn&q=85&s=73e56aa60fdef2dc8152bf929ebc1d52" alt="Generate New Keys button in the Identity Verification section" width="2350" height="686" data-path="images/docs/b24c1fd-Identity_Verification.png" />
    </Frame>

    Descarga el archivo PEM o copia la clave privada, asegurándote de almacenar la clave privada de forma segura.

    <Frame caption="Par de claves de Verificación de Identidad">
      <img src="https://mintcdn.com/onesignal/56ctKxZSV4m5VEkn/images/docs/bc217af-id_keys.png?fit=max&auto=format&n=56ctKxZSV4m5VEkn&q=85&s=b8e99ccdb2f4aafd453063540148ca2e" alt="Identity Verification key pair with private key and PEM download" width="1128" height="966" data-path="images/docs/bc217af-id_keys.png" />
    </Frame>

    <Warning>
      Siempre almacena tus claves privadas en un entorno seguro, como un sistema de gestión de claves. Nunca expongas claves privadas en código del lado del cliente, repositorios públicos o registros.
    </Warning>
  </Step>

  <Step title="Generar JWT de verificación en tu backend">
    La verificación de identidad requiere autenticar al usuario final con tu servidor de autenticación **antes** de iniciar sesión en OneSignal. Cuando el usuario final se autentica con tu backend, genera el token e inclúyelo en la respuesta de autenticación al dispositivo. Si tu aplicación no ejecuta un servidor backend, considera configurar un servidor ligero para verificar usuarios y generar estos tokens.

    #### Carga útil JWT

    El JWT puede tener las siguientes propiedades:

    <ParamField path="iss" required="true">
      Tu ID de Aplicación de OneSignal
    </ParamField>

    <ParamField path="exp" required="true">
      La fecha de expiración del token.
    </ParamField>

    <ParamField path="identity" required="true">
      El alias del usuario.
    </ParamField>

    <ParamField path="subscriptions">
      Requerido solo cuando se agregan suscripciones de Correo electrónico y SMS a un usuario.
    </ParamField>

    #### Firmar el JWT

    Firma el JWT usando el algoritmo ES256. Asegúrate de que tu backend esté configurado para usar este método de firma para evitar problemas de verificación al enviar el JWT a OneSignal. Recomendamos una [Biblioteca JWT](https://jwt.io/libraries) para hacer esto.

    Ejemplo usando [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken):

    <CodeGroup>
      ```typescript Node.js theme={null}
      import jwt from 'jsonwebtoken';

      const APP_ID = process.env['ONESIGNAL_APP_ID']
      const IDENTITY_VERIFICATION_SECRET = process.env['ONESIGNAL_IDENTITY_VERIFICATION_SECRET_KEY']

      // Generates JWT, potentially with subscription claims, for the user identified by the External ID
      function signOneSignalJWT(externalId, subscriptions) {
      return jwt.sign({
      iss: APP_ID,
      exp: Math.floor(Date.now() / 1000) + 3600, // 1-hour expiration
      identity: {
      'external_id': externalId,
      },
      subscriptions
      },
      IDENTITY_VERIFICATION_SECRET,
      { algorithm: 'ES256' });
      }

      // Pass this token to your mobile app to use with the `login` SDK method
      const onesignalJWT = signOneSignalJWT('EXTERNAL_ID');

      ```
    </CodeGroup>

    La clave privada está en el archivo del paso anterior que descargamos del Panel.

    #### Verificar tu JWT

    Antes de integrar con el SDK, verifica que tu JWT se está generando correctamente iniciando tu servidor y llamando al endpoint:

    <CodeGroup>
      ```typescript Node.js theme={null}
        node server.js
      ```
    </CodeGroup>

    <CodeGroup>
      ```bash cURL theme={null}
        curl http://localhost:3000/generate-jwt/your-external-id
      ```
    </CodeGroup>

    Deberías recibir una respuesta como:

    ```json theme={null}
    {
      "jwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
    }
    ```

    Pega el valor del JWT en [jwt.io](https://jwt.io) y confirma que el payload decodificado contiene los siguientes parámetros:

    ```json theme={null}
    {
      "iss": "your-onesignal-app-id",
      "exp": 1234567890,
      "identity": {
        "external_id": "your-external-id"
      }
    }
    ```

    Confirma lo siguiente antes de pasar al siguiente paso:

    * `iss` coincide con tu ID de Aplicación de OneSignal en **Configuración > Claves e IDs**
    * `identity.external_id` está presente y coincide con el valor que pasarás a `OneSignal.login()`
    * `exp` es una marca de tiempo futura — un token expirado será rechazado por OneSignal

    #### Incluir suscripciones

    Idealmente, los detalles de suscripción, como correo electrónico o número de teléfono, se incluyen en la carga útil JWT al iniciar sesión de un usuario. Si estos detalles no están disponibles por adelantado, tu servidor de verificación debe proporcionar un endpoint para generar tokens dinámicamente a medida que la información de suscripción esté disponible.

    Ejemplo: Generar JWT para agregar suscripciones

    <CodeGroup>
      ```typescript Node.js theme={null}
      const subscriptions = [
        {
            "type": "Email",
            "token": "[email protected]"
        },
        {
            "type": "SMS",
            "token": "+12345678"
        }
      ]
      const onesignalJWT = signOneSignalJWT('EXTERNAL_ID', subscriptions)
      ```
    </CodeGroup>
  </Step>

  <Step title="Pasar JWT al método `login`">
    Una vez que tu backend genera el JWT, llama al método `login` con él. Este token asegura que la identidad del usuario sea verificada antes de que se puedan hacer cambios, como agregar una suscripción de correo electrónico o SMS.

    Ejemplo de inicio de sesión:

    <CodeGroup>
      ```java java theme={null}
      String externalId = "YOUR_EXTERNAL_ID";
      String onesignalJWT = "YOUR_JWT_TOKEN";

      OneSignal.login(externalId, onesignalJWT);
      ```

      ```kotlin kotlin theme={null}
      val externalId = "YOUR_EXTERNAL_ID"
      val onesignalJWT = "YOUR_JWT_TOKEN"

      OneSignal.login(externalId, onesignalJWT)
      ```

      ```swift Swift theme={null}
      let externalId = "YOUR_EXTERNAL_ID"
      let onesignalJWT = "YOUR_JWT_TOKEN"

      OneSignal.login(externalId: externalId, token: onesignalJWT)
      ```

      ```c objective-c theme={null}
      NSString* externalId = @"YOUR_EXTERNAL_ID";
      NSString* onesignalJWT = @"YOUR_JWT_TOKEN";

      [OneSignal login:externalId withToken:onesignalJWT];
      ```
    </CodeGroup>
  </Step>

  <Step title="Manejar eventos del ciclo de vida del JWT">
    Necesitarás implementar un endpoint dedicado en tu backend para manejar escenarios como la invalidación de tokens. Este endpoint debe proporcionar un JWT actualizado cuando OneSignal solicite una actualización.

    Ejemplo de manejo de invalidación de token y actualización del JWT:

    <CodeGroup>
      ```java java theme={null}
      OneSignal.addUserJwtInvalidatedListener(event -> {
        // Get the expired user's External ID
        String externalId = event.getExternalId();

        // Fetch a new JWT from your backend for the user
        String onesignalJWT = "yourUpdatedToken";

        // Provide the new JWT to the SDK
        OneSignal.updateUserJwt(externalId, onesignalJWT);
      });
      ```

      ```kotlin kotlin theme={null}
      OneSignal.addUserJwtInvalidatedListener(
         object : IUserJwtInvalidatedListener {
             override fun onUserJwtInvalidated(event: UserJwtInvalidatedEvent) {
               val externalId = event.externalId
               val onesignalJWT = ""
               updateUserJwt(externalId, onesignalJWT)
             }
         },
      )
      ```

      ```swift Swift theme={null}
      class AppDelegate: UIResponder, UIApplicationDelegate, OSUserJwtInvalidatedListener {
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
          // Set self to listen for JWT invalidated events
          OneSignal.addUserJwtInvalidatedListener(self)

          // Remove the JWT listener as needed by calling:
          // `OneSignal.removeUserJwtInvalidatedListener(self)`
        }

        // Required to conform to `OSUserJwtInvalidatedListener` protocol
        func onUserJwtInvalidated(event: OneSignalUser.OSUserJwtInvalidatedEvent) {
          // Get the expired user's External ID
          let externalId = event.externalId

          // Fetch a new JWT from your backend for the user
          let onesignalJWT = "yourUpdatedToken"

          // Provide the new JWT to the SDK
          OneSignal.updateUserJwt(externalId: externalId, token: onesignalJWT)
        }
      }
      ```

      ```c objective-c theme={null}
      @interface MyListener: NSObject<OSUserJwtInvalidatedListener>
      @end

      @implementation MyListener
      - (void)onUserJwtInvalidatedWithEvent:(OSUserJwtInvalidatedEvent * _Nonnull)event {
        // Get the expired user's External ID
        NSString *externalId = event.externalId;

        // Fetch a new JWT from your backend for the user
        NSString *onesignalJWT = @"yourUpdatedToken";

        // Provide the new JWT to the SDK
      	[OneSignal updateUserJwt:externalId withToken:onesignalJWT];
      }

      // Add or remove your User Jwt Invalidated Listener
      [OneSignal addUserJwtInvalidatedListener:myListener];
      [OneSignal removeUserJwtInvalidatedListener:myListener];
      ```
    </CodeGroup>

    Esto asegura que cuando el JWT de un usuario se invalide, se pueda obtener uno nuevo de tu backend y pasarlo a OneSignal. También puedes usar esta función para generar un token con un correo electrónico y número de teléfono, permitiéndote gestionar suscripciones de correo electrónico y SMS si el token creado durante la autenticación no los contiene.
  </Step>

  <Step title="Habilitar verificación de identidad de token en el panel">
    Desde **Configuración > Claves e IDs**, activa **Verificación de Identidad de Token** para habilitar.

    <Frame caption="Habilitando Verificación de Identidad de Token">
      <img src="https://mintcdn.com/onesignal/YOTSrtBSoqdrJ37A/images/docs/4887367-identity_verification_enabled.png?fit=max&auto=format&n=YOTSrtBSoqdrJ37A&q=85&s=26d06ca0a008e841d5206093bfbf2a8c" alt="Token Identity Verification toggle enabled in dashboard settings" width="2350" height="686" data-path="images/docs/4887367-identity_verification_enabled.png" />
    </Frame>

    Una vez habilitado, tu aplicación debe enviar JWTs de OneSignal para verificar la autenticidad de la suscripción. Además, tu aplicación debe llamar al método `login` usando un JWT generado por tu servidor de tokens de verificación de identidad.
  </Step>
</Steps>

## Agregar suscripciones

No necesitas tomar pasos adicionales para agregar suscripciones desde tu aplicación móvil; llamar al método de inicio de sesión maneja esto automáticamente por ti.

<Tabs>
  <Tab title="Agregar un correo electrónico">
    <CodeGroup>
      ```java java theme={null}
      OneSignal.getUser().addEmail(emailAddress);
      ```

      ```kotlin kotlin theme={null}
      OneSignal.getUser().addEmail(emailAddress)
      ```

      ```swift Swift theme={null}
      // Si aún no lo has incluido en tu token JWT, actualiza el JWT con el correo electrónico
      let onesignalJWT = "newTokenThatContainsTheEmailToAdd"
      OneSignal.updateUserJwt(externalId: externalId, token: onesignalJWT)

      // Agregar el correo electrónico
      OneSignal.User.addEmail(emailAddress)
      ```

      ```c objective-c theme={null}
      // Si aún no lo has incluido en tu token JWT, actualiza el JWT con el correo electrónico
      NSString *onesignalJWT = @"newTokenThatContainsTheEmailToAdd";
      [OneSignal updateUserJwt:externalId withToken:onesignalJWT];

      // Agregar el correo electrónico
      [OneSignal.User addEmail:emailAddress];
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Agregar un número de teléfono">
    <CodeGroup>
      ```java java theme={null}
      OneSignal.getUser().addSms(smsNumber);
      ```

      ```kotlin kotlin theme={null}
      OneSignal.getUser().addSms(smsNumber)
      ```

      ```swift Swift theme={null}
      // Si aún no lo has incluido en tu token JWT, actualiza el JWT con el SMS
      let onesignalJWT = "newTokenThatContainsTheSmsToAdd"
      OneSignal.updateUserJwt(externalId: externalId, token: onesignalJWT)

      // Agregar el número de SMS
      OneSignal.User.addSms(smsNumber)
      ```

      ```c objective-c theme={null}
      // Si aún no lo has incluido en tu token JWT, actualiza el JWT con el SMS
      NSString *onesignalJWT = @"newTokenThatContainsTheSmsToAdd";
      [OneSignal updateUserJwt:externalId withToken:onesignalJWT];

      // Agregar el número de SMS
      [OneSignal.User addSms:smsNumber];
      ```
    </CodeGroup>
  </Tab>
</Tabs>

***

## REST API

Cuando la Verificación de Identidad de Token está habilitada, todas las solicitudes a las siguientes APIs deben incluir un JWT generado por el servidor en los encabezados como un token bearer, ej., `Authorization: Bearer <JWT>`.

* [Crear usuario](/reference/create-user)
* [Ver usuario](/reference/view-user)
* [Actualizar usuario](/reference/update-user)
* [Eliminar usuario](/reference/delete-user)
* [Ver identidad de usuario](/reference/fetch-aliases)
* [Crear alias](/reference/create-alias)
* [Eliminar alias](/reference/delete-alias)
* [Crear suscripción](/reference/create-subscription)
* [Actualizar suscripción](/reference/update-subscription)

***

## Preguntas frecuentes

### ¿Es obligatoria la verificación de identidad?

No, pero se recomienda ampliamente. Sin ella, cualquier cliente que conozca el ID de Usuario Externo de un usuario puede hacerse pasar por ese usuario y modificar sus suscripciones o datos.

### ¿Qué ocurre si el JWT expira durante una sesión?

El SDK activa un evento de invalidación de JWT. Implementa `addUserJwtInvalidatedListener` (ver [Manejar eventos del ciclo de vida del JWT](#handle-jwt-lifecycle-events)) para obtener un token actualizado de tu backend y pasarlo a `updateUserJwt`.

### ¿Qué SDKs admiten la verificación de identidad?

Actualmente, el SDK nativo de Android (5.2.0+) y el SDK de iOS (5.3.0+). El soporte para SDK wrapper (Flutter, React Native, Unity, etc.) llegará próximamente.

### ¿Necesito verificación de identidad para la API REST?

Cuando la Verificación de Identidad de Token está habilitada, todas las solicitudes a las [APIs admitidas](#rest-api) deben incluir un JWT generado por el servidor como token bearer en el encabezado `Authorization`. El JWT se genera de la misma manera que para el uso del SDK.

### ¿Qué algoritmo usa el JWT?

La Verificación de Identidad requiere JWTs firmados con el algoritmo **ES256** (ECDSA usando P-256 y SHA-256). Otros algoritmos serán rechazados.

***
