Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Getting Access Token from Google Cloud service account
Forum Updated to NodeBB v4.3 + New Features

Getting Access Token from Google Cloud service account

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 574 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    luca
    wrote on last edited by
    #1

    Hi all,
    I need to retrieve an access token from google cloud using a service account json.

    Here is my code:

    generateJWT(const QString &clientEmail, const QString &privateKey) {
        // Header
        QJsonObject header;
        header["alg"] = "RS256";
        header["typ"] = "JWT";
        QString encodedHeader = base64UrlEncode(QJsonDocument(header).toJson(QJsonDocument::Compact));
    
        qDebug() << "encodedHeader:" << encodedHeader;
        // Payload
        QJsonObject payload;
        payload["iss"] = clientEmail;
        payload["scope"] = "https://www.googleapis.com/auth/firebase.messaging";
        payload["aud"] = "https://oauth2.googleapis.com/token";
        payload["exp"] = QDateTime::currentSecsSinceEpoch() + 3600; // 1 hour expiration
        payload["iat"] = QDateTime::currentSecsSinceEpoch();
        QString encodedPayload = base64UrlEncode(QJsonDocument(payload).toJson(QJsonDocument::Compact));
    
        // Signature
        QString message = encodedHeader + "." + encodedPayload;
        qDebug() << "message:\n" << message;
        QByteArray signature = QMessageAuthenticationCode::hash(message.toUtf8(), privateKey.toUtf8(), QCryptographicHash::Sha256);
        QString encodedSignature = base64UrlEncode(signature);
    
        // JWT
        QString jwt = encodedHeader + "." + encodedPayload + "." + encodedSignature;
        qDebug() << "JTW: "<< jwt;
        return jwt;
    }
    
    getAccessToken() {
    
        QFile keyFile("/mnt/temporanea/Downloads/myproject-1122344956ca77.json");
        if (!keyFile.open(QIODevice::ReadOnly)) {
            qWarning() << "Failed to open key file";
            return;
        }
        QByteArray keyData = keyFile.readAll();
        QJsonDocument keyDoc = QJsonDocument::fromJson(keyData);
        QJsonObject keyObject = keyDoc.object();
        QString clientEmail = keyObject["client_email"].toString();
        QString privateKey = keyObject["private_key"].toString();
    
        qDebug() << clientEmail << privateKey;
    
        // Generate JWT
        QString jwt = generateJWT(clientEmail, privateKey);
    
        // Request access token
        QNetworkRequest request(QUrl("https://oauth2.googleapis.com/token"));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
    
        QUrlQuery params;
        params.addQueryItem("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
        params.addQueryItem("assertion", jwt);
    
        QNetworkReply *reply = manager.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
        connect(reply, &QNetworkReply::finished, [reply] {
            if (reply->error() == QNetworkReply::NoError) {
                QByteArray response = reply->readAll();
                QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
                QString accessToken = jsonDoc.object()["access_token"].toString();
                qDebug() << "Access Token:" << accessToken;
                // Use the access token for API calls
            } else {
                qWarning() << "Error:" << reply->errorString();
            }
            reply->deleteLater();
        });
    
    }
    
    base64UrlEncode(const QByteArray &data) {
        QByteArray encoded = data.toBase64();
        encoded = encoded.replace('+', '-').replace('/', '_').replace("=", "");
        return QString::fromUtf8(encoded);
    }
    
    

    When executing I get:

    Error: "Error transferring https://oauth2.googleapis.com/token - server replied: Bad Request"
    

    Did anyone manage to get the access token this way?

    Thanks

    I 1 Reply Last reply
    0
    • L luca

      Hi all,
      I need to retrieve an access token from google cloud using a service account json.

      Here is my code:

      generateJWT(const QString &clientEmail, const QString &privateKey) {
          // Header
          QJsonObject header;
          header["alg"] = "RS256";
          header["typ"] = "JWT";
          QString encodedHeader = base64UrlEncode(QJsonDocument(header).toJson(QJsonDocument::Compact));
      
          qDebug() << "encodedHeader:" << encodedHeader;
          // Payload
          QJsonObject payload;
          payload["iss"] = clientEmail;
          payload["scope"] = "https://www.googleapis.com/auth/firebase.messaging";
          payload["aud"] = "https://oauth2.googleapis.com/token";
          payload["exp"] = QDateTime::currentSecsSinceEpoch() + 3600; // 1 hour expiration
          payload["iat"] = QDateTime::currentSecsSinceEpoch();
          QString encodedPayload = base64UrlEncode(QJsonDocument(payload).toJson(QJsonDocument::Compact));
      
          // Signature
          QString message = encodedHeader + "." + encodedPayload;
          qDebug() << "message:\n" << message;
          QByteArray signature = QMessageAuthenticationCode::hash(message.toUtf8(), privateKey.toUtf8(), QCryptographicHash::Sha256);
          QString encodedSignature = base64UrlEncode(signature);
      
          // JWT
          QString jwt = encodedHeader + "." + encodedPayload + "." + encodedSignature;
          qDebug() << "JTW: "<< jwt;
          return jwt;
      }
      
      getAccessToken() {
      
          QFile keyFile("/mnt/temporanea/Downloads/myproject-1122344956ca77.json");
          if (!keyFile.open(QIODevice::ReadOnly)) {
              qWarning() << "Failed to open key file";
              return;
          }
          QByteArray keyData = keyFile.readAll();
          QJsonDocument keyDoc = QJsonDocument::fromJson(keyData);
          QJsonObject keyObject = keyDoc.object();
          QString clientEmail = keyObject["client_email"].toString();
          QString privateKey = keyObject["private_key"].toString();
      
          qDebug() << clientEmail << privateKey;
      
          // Generate JWT
          QString jwt = generateJWT(clientEmail, privateKey);
      
          // Request access token
          QNetworkRequest request(QUrl("https://oauth2.googleapis.com/token"));
          request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
      
          QUrlQuery params;
          params.addQueryItem("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
          params.addQueryItem("assertion", jwt);
      
          QNetworkReply *reply = manager.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
          connect(reply, &QNetworkReply::finished, [reply] {
              if (reply->error() == QNetworkReply::NoError) {
                  QByteArray response = reply->readAll();
                  QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
                  QString accessToken = jsonDoc.object()["access_token"].toString();
                  qDebug() << "Access Token:" << accessToken;
                  // Use the access token for API calls
              } else {
                  qWarning() << "Error:" << reply->errorString();
              }
              reply->deleteLater();
          });
      
      }
      
      base64UrlEncode(const QByteArray &data) {
          QByteArray encoded = data.toBase64();
          encoded = encoded.replace('+', '-').replace('/', '_').replace("=", "");
          return QString::fromUtf8(encoded);
      }
      
      

      When executing I get:

      Error: "Error transferring https://oauth2.googleapis.com/token - server replied: Bad Request"
      

      Did anyone manage to get the access token this way?

      Thanks

      I Offline
      I Offline
      IgKh
      wrote on last edited by
      #3

      @luca You are signing the JWT incorrectly. The JWT header says that the algorithm is RS256 which means RSA signature of SHA-256 hashed payload, but the actual signature is a HMAC (which would fit an alg value of HS256).

      If RS256 is expected signature algorithm, you need to do a RSA signature, which I don't believe Qt has built-in. You'll need an additional library for that.

      P.S QByteArray::toBase64 takes an options argument, that you can use to tell it to use the URL-safe base64 variant.

      1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Hi,

        Out of curiosity, why not use the Qt NetworkAuth module ?

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        L 1 Reply Last reply
        0
        • L luca

          Hi all,
          I need to retrieve an access token from google cloud using a service account json.

          Here is my code:

          generateJWT(const QString &clientEmail, const QString &privateKey) {
              // Header
              QJsonObject header;
              header["alg"] = "RS256";
              header["typ"] = "JWT";
              QString encodedHeader = base64UrlEncode(QJsonDocument(header).toJson(QJsonDocument::Compact));
          
              qDebug() << "encodedHeader:" << encodedHeader;
              // Payload
              QJsonObject payload;
              payload["iss"] = clientEmail;
              payload["scope"] = "https://www.googleapis.com/auth/firebase.messaging";
              payload["aud"] = "https://oauth2.googleapis.com/token";
              payload["exp"] = QDateTime::currentSecsSinceEpoch() + 3600; // 1 hour expiration
              payload["iat"] = QDateTime::currentSecsSinceEpoch();
              QString encodedPayload = base64UrlEncode(QJsonDocument(payload).toJson(QJsonDocument::Compact));
          
              // Signature
              QString message = encodedHeader + "." + encodedPayload;
              qDebug() << "message:\n" << message;
              QByteArray signature = QMessageAuthenticationCode::hash(message.toUtf8(), privateKey.toUtf8(), QCryptographicHash::Sha256);
              QString encodedSignature = base64UrlEncode(signature);
          
              // JWT
              QString jwt = encodedHeader + "." + encodedPayload + "." + encodedSignature;
              qDebug() << "JTW: "<< jwt;
              return jwt;
          }
          
          getAccessToken() {
          
              QFile keyFile("/mnt/temporanea/Downloads/myproject-1122344956ca77.json");
              if (!keyFile.open(QIODevice::ReadOnly)) {
                  qWarning() << "Failed to open key file";
                  return;
              }
              QByteArray keyData = keyFile.readAll();
              QJsonDocument keyDoc = QJsonDocument::fromJson(keyData);
              QJsonObject keyObject = keyDoc.object();
              QString clientEmail = keyObject["client_email"].toString();
              QString privateKey = keyObject["private_key"].toString();
          
              qDebug() << clientEmail << privateKey;
          
              // Generate JWT
              QString jwt = generateJWT(clientEmail, privateKey);
          
              // Request access token
              QNetworkRequest request(QUrl("https://oauth2.googleapis.com/token"));
              request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
          
              QUrlQuery params;
              params.addQueryItem("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer");
              params.addQueryItem("assertion", jwt);
          
              QNetworkReply *reply = manager.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
              connect(reply, &QNetworkReply::finished, [reply] {
                  if (reply->error() == QNetworkReply::NoError) {
                      QByteArray response = reply->readAll();
                      QJsonDocument jsonDoc = QJsonDocument::fromJson(response);
                      QString accessToken = jsonDoc.object()["access_token"].toString();
                      qDebug() << "Access Token:" << accessToken;
                      // Use the access token for API calls
                  } else {
                      qWarning() << "Error:" << reply->errorString();
                  }
                  reply->deleteLater();
              });
          
          }
          
          base64UrlEncode(const QByteArray &data) {
              QByteArray encoded = data.toBase64();
              encoded = encoded.replace('+', '-').replace('/', '_').replace("=", "");
              return QString::fromUtf8(encoded);
          }
          
          

          When executing I get:

          Error: "Error transferring https://oauth2.googleapis.com/token - server replied: Bad Request"
          

          Did anyone manage to get the access token this way?

          Thanks

          I Offline
          I Offline
          IgKh
          wrote on last edited by
          #3

          @luca You are signing the JWT incorrectly. The JWT header says that the algorithm is RS256 which means RSA signature of SHA-256 hashed payload, but the actual signature is a HMAC (which would fit an alg value of HS256).

          If RS256 is expected signature algorithm, you need to do a RSA signature, which I don't believe Qt has built-in. You'll need an additional library for that.

          P.S QByteArray::toBase64 takes an options argument, that you can use to tell it to use the URL-safe base64 variant.

          1 Reply Last reply
          1
          • SGaistS SGaist

            Hi,

            Out of curiosity, why not use the Qt NetworkAuth module ?

            L Offline
            L Offline
            luca
            wrote on last edited by
            #4

            @SGaist AFAIK Qt NetworkAuth can be used to authenticate via browser. Can't be used for server-to-server communication using a service account.

            @IgKh said in Getting Access Token from Google Cloud service account:

            @luca You are signing the JWT incorrectly. The JWT header says that the algorithm is RS256 which means RSA signature of SHA-256 hashed payload, but the actual signature is a HMAC (which would fit an alg value of HS256).

            If RS256 is expected signature algorithm, you need to do a RSA signature, which I don't believe Qt has built-in. You'll need an additional library for that.

            P.S QByteArray::toBase64 takes an options argument, that you can use to tell it to use the URL-safe base64 variant.

            Thanks, this could be the reason. Do you know how to do that using openssl?

            1 Reply Last reply
            0
            • L Offline
              L Offline
              luca
              wrote on last edited by
              #5

              It seems this code works fine:
              https://jorisvergeer.nl/2023/03/22/c-qt-openssl-jwt-minimalistic-implementation-to-create-a-signed-jtw-token/

              1 Reply Last reply
              0
              • L luca has marked this topic as solved on

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved