【问题标题】:Using Amazon AWS Cognito `.well-known/jwks.json` data fails to base64 decode some fields使用 Amazon AWS Cognito `.well-known/jwks.json` 数据无法对某些字段进行 base64 解码
【发布时间】:2017-02-20 03:33:22
【问题描述】:

使用 Amazon AWS Cognito Federated Identities 并解析位于:
https://cognito-identity.amazonaws.com/.well-known/jwks_uri 的数据时,如下所示:

{"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"}, 
 ... }

这可以很好地使用此代码解码n 字段(Kotlin 调用 JDK 8 Base64 类):

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

但是当使用 Cognito User Pools 时,其 URL 中的数据格式为:
https://cognito-idp.${REGION}.amazonaws.com/${POOLID}/.well-known/jwks.json

它具有相同类型的数据,但不会解码。相反,我最终会遇到以下错误:

非法base64字符5f

因为这是一个下划线 _ 并且在 Base64 URL 字母表中,我尝试将我的解码更改为:

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

但随后第一组数据不再正确解码,因为它包含/ 和其他用于Base64 URL 编码的无效字符。

有没有一种方法可以用同一个解码器处理这两个jwks 数据集?!?

注意: 这个问题是作者(Self-Answered Questions)有意编写和回答的,以便在SO中分享有趣问题的解决方案。

【问题讨论】:

    标签: java amazon-web-services kotlin amazon-cognito


    【解决方案1】:

    问题在于,Amazon AWS Cognito 团队使用两种不同的 Base64 编码字母表来处理基本相同的事情。因此,您需要检测正在使用哪个。

    如果编码后的字符串以=结尾或者包含+或者/那么肯定是正常的Base64.getDecoder()。如果它包含-_,那么它肯定是Base64.getUrlDecoder()。否则没有什么特别的,最好使用Base64.getUrlDecoder(),因为你不知道长度是否需要填充。

    这翻译为(在 Kotlin 中,但逻辑上适用于任何语言):

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

    这对于任何具有 Base64 解码的语言来说都是一个问题,因为它们可能是松散的并忽略无效字符(有些会),或者它们可能是严格的并引发异常。一些 Base64 编码/解码的测试网站也表现出这两种行为,并且无声忽略无效字符是危险的。稍后使用解码结果会出错。

    【讨论】:

    • 确实 5f 是 Base64 的 URL 安全变体的下划线
    【解决方案2】:

    您可以尝试使用 Base64 解码的 apache 变体 (org.apache.commons.codec.binary.Base64)。

    decodeBase64(String base64String) 方法可以无缝处理 base64 和 base64 url​​ 安全编码。 isBase64 方法提供了一个检查来检测字符串是否以 base64 或 base64 url​​ 安全编码。

    【讨论】:

    • 太好了,在这种情况下,我想继续使用 JDK 版本,尽管对于其他项目,其中 commons 编解码器在依赖项中很重要。
    猜你喜欢
    • 1970-01-01
    • 2017-07-15
    • 2020-04-02
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 2018-05-07
    • 1970-01-01
    • 2017-06-07
    相关资源
    最近更新 更多