Autenticación de dos factores con Java y Google Authenticator

Autenticación de dos factores con Java y Google Authenticator

@programacion

Estoy más que seguro de que cada uno de ustedes tiene al menos una cuenta con autenticación de dos factores (2FA) habilitada. Pero si aún no está familiarizado con 2FA, le daré una explicación general.

Es un segundo paso en la secuencia de inicio de sesión que le pide que ingrese un código de 6 dígitos que se le envió por correo electrónico, mensaje de texto o la aplicación Google Authenticator y este código caduca en 30 o 60 segundos. Este segundo paso de autenticación hace que su cuenta sea más segura, porque incluso si alguien conoce su nombre de usuario y contraseña, aún necesita su dispositivo móvil físico para ver el código 2FA que se le envió. Este enfoque es muy utilizado en casi todas las aplicaciones, especialmente si esta aplicación tiene que ver con dinero, criptomonedas, bancos, transacciones, etc.

Entonces, en este artículo, como habrá notado, hablaremos sobre el uso de la aplicación Google Authenticator con su aplicación basada en Java. ¡Empecemos!

En primer lugar, creemos un proyecto maven y agreguemos las siguientes dependencias:

En primer lugar, creemos un proyecto maven y agreguemos las siguientes dependencias:

<dependency> 
    <groupId>de.taimos</groupId> 
    <artifactId>totp</artifactId> 
    <version>1.0</version> 
</dependency> 

<dependency> 
    <groupId>commons-codec</groupId> 
    <artifactId>commons -codec</artifactId> 
    <version>1.10</version> 
</dependency> 

<dependency> 
    <groupId>com.google.zxing</groupId> 
    <artifactId>javase</artifactId> 
    <version>3.2.1</version > 
</dependencia>

He aquí por qué necesitamos esas dependencias en nuestro proyecto:

  • totp : el algoritmo de contraseña de un solo uso basado en el tiempo (TOTP) es una extensión del algoritmo de contraseña de un solo uso basado en HMAC (HOTP) que genera una contraseña de un solo uso al tomar la singularidad de la hora actual.
  • commons-codec : para convertir entradas a hexadecimal y base32.
  • zxing - biblioteca para generar códigos QR.

También debe instalar la aplicación Google Authenticator en su teléfono inteligente. Es totalmente gratis y está disponible en App Store y Play Market. Para agregar una nueva entrada a la aplicación Google Authenticator, debe ingresar manualmente una clave secreta o escanear un código QR. Te mostraré cómo usar ambos en este tutorial. Comencemos con el manual uno primero.

Google Authenticator requiere una clave secreta de 20 bytes codificada como cadena base32. Necesitamos generar esta clave usando el siguiente código:

public static String generateSecretKey() {
    SecureRandom random = new SecureRandom();
    byte[] bytes = new byte[20];
    random.nextBytes(bytes);
    Base32 base32 = new Base32();
    return base32.encodeToString(bytes);
}

Después de ejecutar este método, debería ver la cadena generada con 32 caracteres. Escriba esta cadena en algún lugar, ya que esta es nuestra clave secreta y la usaremos más adelante.

QDWSM3OYBPGTEVSPB5FKVDM3CSNCWHVK

Ahora abra su aplicación Google Authenticator. Presione el botón ' más ' para agregar una nueva entrada y seleccione ' Entrada manual'. En el campo ' Cuenta' ingrese su dirección de correo electrónico o cualquier nombre y en el campo ' Clave ' pegue nuestra clave secreta. Pulse el botón Guardar. Debería ver su entrada en la lista con un código de 6 dígitos que cambia cada 30 segundos.

Ahora, escribamos un método que convierta las claves secretas codificadas en base32 en hexadecimales y use el TOTP para convertirlas en códigos de 6 dígitos en función de la hora actual.

public static String getTOTPCode(String secretKey) {
    Base32 base32 = new Base32();
    byte[] bytes = base32.decode(secretKey);
    String hexKey = Hex.encodeHexString(bytes);
    return TOTP.getOTP(hexKey);
}

Ahora ejecutemos el siguiente código para generar un código de 6 dígitos basado en el tiempo sincronizado con Google Authenticator.

String secretKey = "QDWSM3OYBPGTEVSPB5FKVDM3CSNCWHVK";
String lastCode = null;
while (true) {
    String code = getTOTPCode(secretKey);
    if (!code.equals(lastCode)) {
        System.out.println(code);
    }
    lastCode = code;
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {};
}

Si hizo todo correctamente, debería ver el código de 6 dígitos que se muestra en la consola cada 30 segundos y este código debería sincronizarse con el código que se muestra en Google Authenticator. Si no están sincronizados, asegúrese de que la hora en su PC y dispositivo móvil esté sincronizada.

Hemos terminado con el ejemplo de entrada manual, así que pasemos al código QR, que es más fácil de usar y se usa en la mayoría de los casos.

En primer lugar, necesitamos recibir los datos del código de barras de Google. Requiere algún formato especial, así que aquí está nuestro método para generar estos datos.

public static String getGoogleAuthenticatorBarCode(String secretKey, String account, String issuer) {
    try {
        return "otpauth://totp/"
                + URLEncoder.encode(issuer + ":" + account, "UTF-8").replace("+", "%20")
                + "?secret=" + URLEncoder.encode(secretKey, "UTF-8").replace("+", "%20")
                + "&issuer=" + URLEncoder.encode(issuer, "UTF-8").replace("+", "%20");
    } catch (UnsupportedEncodingException e) {
        throw new IllegalStateException(e);
    }
}

Aquí hay algunas notas sobre la cadena generada arriba:

  • La cuenta es la identificación del usuario en el sistema. Por lo general, es el correo electrónico o el nombre de usuario. Se utiliza para etiquetar entradas dentro de Google Authenticator.
  • Emisor es el nombre de una empresa u organización y también se utiliza con fines de etiquetado.
  • Todos los valores dinámicos deben estar codificados como URL.
  • Google Authenticator no parece tratar con espacios codificados como signos más. La codificación de espacios como %20 parece funcionar.

Ahora ejecute el código anterior con algún nombre de cuenta de prueba, nombre de emisor y clave secreta generada previamente:

String secretKey = "QDWSM3OYBPGTEVSPB5FKVDM3CSNCWHVK";
String email = "test@gmail.com";
String companyName = "My Awesome Company";
String barCodeUrl = Utils.getGoogleAuthenticatorBarCode(secretKey, email, companyName);
System.out.println(barCodeUrl);

Debería recibir una cadena en el siguiente formato:

otpauth://totp/Awesome%20Company%3Atest%40gmail.com?secret=7t4gabg72liipmq7n43lt3cw66fel4iz&issuer=Awesome%20Company

Ahora queda el último paso: generar un código QR. Usemos la biblioteca ZXing para hacerlo.

public static void createQRCode(String barCodeData, String filePath, int height, int width)
        throws WriterException, IOException {
    BitMatrix matrix = new MultiFormatWriter().encode(barCodeData, BarcodeFormat.QR_CODE,
            width, height);
    try (FileOutputStream out = new FileOutputStream(filePath)) {
        MatrixToImageWriter.writeToStream(matrix, "png", out);
    }
}

Llamar a este método con la cadena devuelta por el método en el paso anterior como primer argumento escribirá una imagen PNG en la ruta especificada con la altura y el ancho especificados.

Continúe e intente usar su imagen generada con la opción "Escanear código de barras" que vio anteriormente en Google Authenticator. Después de escanear este código QR, debería ver una nueva entrada en la lista de entradas de Google Authenticator.

Podemos simular el inicio de sesión del usuario en el sistema. Imaginemos que el usuario ingresó sus credenciales y ahora necesita ingresar el código 2FA de Google Authenticator. Aquí está el fragmento de código más fácil:

Scanner scanner = new Scanner(System.in);
String code = scanner.nextLine();
if (code.equals(getTOTPCode(secretKey))) {
    System.out.println("Logged in successfully");
} else {
    System.out.println("Invalid 2FA Code");
}

Por supuesto, esto es solo un pseudocódigo, pero simula el flujo 2FA real y le muestra si hizo todo correctamente.

Conclusión

Ahora conoce los conceptos básicos de la autenticación de dos factores y puede intentar integrarla en su aplicación basada en web con un pequeño esfuerzo para agregar más seguridad a su aplicación.

Fuentes:

https://medium.com/@ihorsokolyk/two-factor-authentication-with-java-and-google-authenticator-9d7ea15ffee6

https://openauthentication.org/

Report Page