Thalhammer / jwt-cpp

A header only library for creating and validating json web tokens in c++
https://thalhammer.github.io/jwt-cpp/
MIT License
915 stars 243 forks source link

JWT generation failed: failed to load key: bio read failed #363

Closed francoamato closed 1 month ago

francoamato commented 1 month ago

What happened?

I am trying to create an Apple Login mechanism using Qt and C++. I read that that, unlike Google, with Apple the secret key must be in JWT format so I tried to do it using the jwt-cpp library. I installed jwt-cpp using vcpkg

vcpkg install jwt-cpp

My .p8 file content is: -----BEGIN PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg6xMHDwAqe0dn4myO mrkVRZLNTr39MK9nOzFz5b55uaWgCgYIKoZIzj0DAQehRANCAAQKY4KrSI6xxVaB A5Cdm9/GXfC+obbw/8uFu3y4HZa6NxGTuT+dNhc0EXB5EkEPSY3iUinBn5XqCJke 4wHd8uUV -----END PRIVATE KEY-----

My code throws the following exception: JWT generation failed: failed to load key: bio read failed

I need a help in understanding why I am getting such error and if there is a way to solve it

How To Reproduce?

QString AppleLogin::generateClientSecret()
{
    // 1. Read private key from file
    std::string privateKeyPath = "AuthKey_HUC29345UK.p8";

    QFile keyFile(QString::fromStdString(privateKeyPath));
    if (!keyFile.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qWarning() << "Failed to open private key file";
        return QString();
    }

    QByteArray keyData = keyFile.readAll();
    keyFile.close();

    std::string privateKey = keyData.toStdString();

    try {
        // 2. Get current time and calculate expiration (6 months)
        auto now = std::chrono::system_clock::now();
        auto exp = now + std::chrono::seconds(15777000);

        // 3. Create the JWT
        const std::string KEY_ID = "HUC29345UK";
        const std::string TEAM_ID = "JDC2Z4S2GN";
        const std::string CLIENT_ID = "com.bb.launcher.service";

        auto token = jwt::create()
                         .set_issuer(TEAM_ID) // Team ID
                         .set_type("JWT")
                         .set_subject(CLIENT_ID) // Client ID
                         .set_audience("https://appleid.apple.com") // Apple audience
                         .set_issued_at(now)
                         .set_expires_at(exp)
                         .set_header_claim("kid", jwt::claim(KEY_ID)) // Key ID
                         .sign(jwt::algorithm::es256(privateKey, "", "", ""));

        return QString::fromStdString(token);
    }
    catch (const std::exception &e)
    {
        qWarning() << "JWT generation failed:" << e.what();
        return QString();
    }
}

Version

0.7.0

What OS are you seeing the problem on?

Windows

What compiler are you seeing the problem on?

MSVC

Relevant log output

JWT generation failed: failed to load key: bio read failed

Code of Conduct

prince-chrismc commented 1 month ago

OpenSSL works with PEM format. Seems like Apple exporting the pubkey pair in .P8 is normal... you just need to convert it to pem.

https://github.com/lcobucci/jwt/issues/244 https://forums.developer.apple.com/forums/thread/689212

https://stackoverflow.com/a/64558316/8480874