El uso de datos de Amazon AWS Cognito `.well-known / jwks.json` falla al decodificar base64 algunos campos

Al utilizar Identidades federadas de Amazon AWS Cognito y analizar los datos en:
https://cognito-identity.amazonaws.com/.well-known/jwks_uri que se ve así:

 {"keys":[ {"kty":"RSA", "alg":"RS512", "use":"sig", "kid":"ap-northeast-11", "n":"AI7mc1assO5n6yB4b7jPCFgVLYPSnwt4qp2BhJVAmlXRntRZ5w4910oKNZDOr4fe/BWOI2Z7upUTE/ICXdqirEkjiPbBN/duVy5YcHsQ5+GrxQ/UbytNVN/NsFhdG8W31lsE4dnrGds5cSshLaohyU/aChgaIMbmtU0NSWQ+jwrW8q1PTvnThVQbpte59a0dAwLeOCfrx6kVvs0Y7fX7NXBbFxe8yL+JR3SMJvxBFuYC+/om5EIRIlRexjWpNu7gJnaFFwbxCBNwFHahcg5gdtSkCHJy8Gj78rsgrkEbgoHk29pk8jUzo/O/GuSDGw8qXb6w0R1+UsXPYACOXM8C8+E=", "e":"AQAB"}, ... } 

Esto funciona bien decodificando el n campo usando este código ( Kotlin llamando a la class JDK 8 Base64 ):

 Base64.getDecoder().decode(encodedN.toByteArray()) 

Pero al usar Cognito User Pools que tiene datos en una URL en forma de:
https://cognito-idp.${REGION}.amazonaws.com/${POOLID}/.well-known/jwks.json

Tiene el mismo tipo de datos, pero no se decodificará. En cambio, termino con errores como:

Illegal base64 character 5f

Como se trata de un guión bajo _ en el alfabeto de la URL de Base64 , traté de cambiar mi desencoding a:

 Base64.getUrlDecoder().decode(encodedN.toByteArray()) 

Pero luego el primer set de datos ya no se decodifica correctamente porque contiene / y otros caracteres no válidos para la encoding URL de Base64 .

¿Hay algún método que pueda manejar estos jwks sets de datos jwks con el mismo decodificador?!?

Nota: esta pregunta fue escrita y respondida intencionalmente por el autor ( Preguntas que responden por sí mismas ), de modo que las soluciones para problemas interesantes se comparten en SO.

El problema es que el equipo de Amazon AWS Cognito está usando dos alfabetos de encoding Base64 diferentes básicamente para lo mismo. Por lo tanto, deberá detectar cuál se está utilizando.

Si la cadena codificada termina con = o contiene + o / entonces definitivamente es el Base64.getDecoder() normal. Si contiene un - o _ entonces definitivamente es el Base64.getUrlDecoder() . De lo contrario, no hay nada especial y es mejor usar Base64.getUrlDecoder() porque no sabes si la longitud necesitaría relleno o no.

Esto se traduce a ( en Kotlin, pero lógicamente es aplicable a cualquier idioma ):

 fun base64SafeDecoder(encoded: String): ByteArray { val decoder = if (encoded.endsWith('=') || encoded.any { it == '+' || it == '/' }) { Base64.getDecoder() } else { Base64.getUrlDecoder() } return decoder.decode(encoded.toByteArray()) } 

Esto sería un problema para cualquier lenguaje que tenga deencoding Base64 porque podrían estar sueltos e ignorar el carácter no válido (algunos lo hacen), o podrían ser estrictos e include una exception. Algunos sitios web de testing para la encoding / deencoding de Base64 exhiben ambos comportamientos también, y el ignorar silenciosamente los caracteres no válidos es peligroso. A continuación, tendrá un error más tarde utilizando los resultados de la deencoding más tarde.

Puede intentar usar la variante apache de la deencoding Base64 (org.apache.commons.codec.binary.Base64).

El método decodeBase64 (String base64String) maneja las codificaciones seguras url base64 y base64 sin problemas. Y el método isBase64 proporciona una comprobación para detectar si una cadena está codificada en base64 url ​​o base64 url ​​safe.

  • Comtesting si EditText está vacío. Kotlin android
  • Cómo asignar una cadena JSON al map de Kotlin
  • Seguridad nula en las bibliotecas henetworkingadas de Java utilizadas en los proyectos de Kotlin
  • La configuration regional de Spring Boot Controller no cambia con el parámetro
  • Enum.valueOf en Kotlin
  • Kotlin coroutines en Android: ¿Por qué usar bg () de Anko en lugar de async ()?
  • Obtener files adjuntos de publicaciones de Facebook devolver NullPointerException
  • Intento de migrar en canario 5
  • Creación de instancia pública de class interna privada en Kotlin
  • sincronizar getters / setters de properties
  • Kotlin - Lista dentro de un filter de list