Как проверить JWT с помощью JWK (ColdFusion)

#java #coldfusion #jwt #cfml #coldbox

#java #coldfusion #jwt #cfml #coldbox

Вопрос:

В настоящее время я пытаюсь проверить подпись JWT, используя открытый ключ RSA, созданный на основе URL-адреса JWKS. Я использую для этого некоторые объекты Java, но моя проблема в том, что верификатор подписи Java не просто принимает строку обычного текста, декодированную в двоичный код, в качестве аргумента, он принимает свою собственную проприетарную двоичную декодированную «подпись».

Итак, мне просто интересно, что я могу сделать, чтобы преобразовать мою обычную текстовую подпись в тип данных, который ожидает функция Java Signature verify() .

Вот мой текущий код:

 private function validate_jwt_signature(rc) {
    var id_token = listToArray(rc.id_token, ".");

    if (listToArray(id_token[2], "")[len(id_token[2])] != "=") {
            id_token[2] = id_token[2] amp; "=";
        }

    var header = deserializeJSON(base64urldecode(id_token[1]));
    var payload = deserializeJSON(base64urldecode(id_token[2]));
    var body = id_token[1] amp; "." amp; id_token[2];
    var signature = id_token[3];

    cfhttp(url="https://lti-ri.imsglobal.org/platforms/53/platform_keys/48.json", method="GET", result="key");

    var platformPubKey = deserializeJSON(key.filecontent).keys[1].n;

    createObject( "java", "java.security.Security" )
        .addProvider( createObject( "java", "org.bouncycastle.jce.provider.BouncyCastleProvider" ).init());

    var platformPubKey = reReplace( platformPubKey, "-", " ", "all" );
    var platformPubKey = reReplace( platformPubKey, "_", "/", "all" );
    var pemKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA" amp; platformPubKey amp; "IDAQAB";
    var publicKeySpec = createObject( "java", "java.security.spec.X509EncodedKeySpec" )
        .init(binaryDecode( pemKey, "base64" ));

    var publicKey = createObject( "java", "java.security.KeyFactory" )
        .getInstance( javaCast( "string", "RSA" ) )
        .generatePublic( publicKeySpec );

    var verifier = createObject( "java", "java.security.Signature" )
        .getInstance( javaCast( "string", 'SHA256withRSA' ));

    var verifier.initVerify( publicKey );
    var verifier.update( charsetDecode( body, "utf-8" ) );
    var signature = reReplace( signature, "-", " ", "all" );
    var signature = reReplace( signature, "_", "/", "all" );
    var verified = verifier.verify( charsetDecode(signature, "utf-8"));

    return verified;
}
  

Этот код выполняется и не выдает ошибку, но он всегда возвращает false, даже когда я знаю, что подпись действительна.

Комментарии:

1. Это необходимо для предоставления двоичной подписи верификатору. Используйте verifier.verify(Base64.getUrlDecoder().decode(signature)); . Чтобы избежать ошибок, вы можете создать открытый ключ с помощью new RSAPublicKeySpec (modulus, pubExp) вместо ручного создания ключа PEM (я не знаю, работает ли ваш код)

2. Хорошее место. Я заметил все инструкции replace () и просто собирался спросить, была ли подпись закодирована в base64. Если это так, используйте binaryDecode(signature, "base64") вместо charsetDecode() .

3. Я заметил, что вы включили coldbox тег в свой вопрос, поэтому я хотел передать это на случай, если это может быть полезно. В ForgeBox есть модуль под названием cbSecurity , который имеет возможность генерировать, декодировать и аутентифицировать токены JWT ( forgebox.io/view/cbsecurity ). Если вы посмотрите на службу JWT, вы можете получить некоторые дополнительные подсказки.

4. Это, вероятно, лучший пакет JWT — forgebox.io/view/jwt-cfml Это и forgebox.io/view/jwt являются двумя наиболее популярными пакетами

5. @pedrofb не могли бы вы привести пример того, как получить модуль и Pubexp с помощью coldfusion? Я действительно борюсь с этой частью, поскольку она включает в себя использование класса ‘Interface RSAPublicKey’ — docs.oracle.com/javase/8/docs/api/java/security/interfaces /…