Ref T730, added jwt JSON token decoding for server connection

This commit is contained in:
Klaus Basan
2019-09-19 13:01:09 +02:00
committed by Mat Sutcliffe
parent a37c9a8772
commit a1281eff3f
2 changed files with 45 additions and 13 deletions

View File

@@ -7,6 +7,8 @@
*/ */
#include "apiserverconnection.h" #include "apiserverconnection.h"
#include "blackmisc/network/external/qjsonwebtoken.h"
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
#include <QUrl> #include <QUrl>
@@ -26,11 +28,12 @@ namespace BlackCore
qDebug() << "ApiServerConnection instantiated"; qDebug() << "ApiServerConnection instantiated";
} }
void ApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion) bool ApiServerConnection::connectTo(const QString &username, const QString &password, const QUuid &networkVersion)
{ {
m_username = username; m_username = username;
m_password = password; m_password = password;
m_networkVersion = networkVersion; m_networkVersion = networkVersion;
m_isAuthenticated = false;
m_watch.start(); m_watch.start();
QUrl url(m_address); QUrl url(m_address);
@@ -52,19 +55,47 @@ namespace BlackCore
while (! reply->isFinished()) { loop.exec(); } while (! reply->isFinished()) { loop.exec(); }
qDebug() << "POST api/v1/auth (" << m_watch.elapsed() << "ms)"; qDebug() << "POST api/v1/auth (" << m_watch.elapsed() << "ms)";
if (reply->error() != QNetworkReply::NoError) if (reply->error() != QNetworkReply::NoError)
{ {
qWarning() << reply->errorString(); qWarning() << reply->errorString();
return; return false;
} }
// JWT authentication token
m_serverToUserOffsetMs = 0;
m_expiryLocalUtc = QDateTime(); // clean up
m_jwt = reply->readAll().trimmed(); m_jwt = reply->readAll().trimmed();
// TODO JwtSecurityToken. Now we assume its 6 hours qint64 lifeTimeSecs = -1;
m_serverToUserOffset = 0; qint64 serverToUserOffsetSecs = -1;
m_expiryLocalUtc = QDateTime::currentDateTimeUtc().addSecs(6 * 60 * 60); do
m_isAuthenticated = true; {
const QString jwtToken(m_jwt);
QJsonWebToken token = QJsonWebToken::fromTokenAndSecret(jwtToken, "");
// get decoded header and payload
// QString strHeader = token.getHeaderQStr();
// QString strPayload = token.getPayloadQStr();
const QJsonDocument doc = token.getPayloadJDoc();
if (doc.isEmpty() || !doc.isObject()) { break; }
const qint64 validFromSecs = doc.object().value("nbf").toInt(-1);
if (validFromSecs < 0) { break; }
const qint64 localSecsSinceEpoch = QDateTime::currentSecsSinceEpoch();
serverToUserOffsetSecs = validFromSecs - localSecsSinceEpoch;
const qint64 serverExpirySecs = doc.object().value("exp").toInt();
const qint64 expiryLocalUtc = serverExpirySecs - serverToUserOffsetSecs;
lifeTimeSecs = expiryLocalUtc - localSecsSinceEpoch;
}
while (false);
if (lifeTimeSecs > 0)
{
m_serverToUserOffsetMs = serverToUserOffsetSecs * 1000;
m_expiryLocalUtc = QDateTime::currentDateTimeUtc().addSecs(lifeTimeSecs);
m_isAuthenticated = true;
}
return m_isAuthenticated;
} }
PostCallsignResponseDto ApiServerConnection::addCallsign(const QString &callsign) PostCallsignResponseDto ApiServerConnection::addCallsign(const QString &callsign)
@@ -96,6 +127,7 @@ namespace BlackCore
void ApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json) void ApiServerConnection::postNoResponse(const QString &resource, const QJsonDocument &json)
{ {
Q_UNUSED(json);
if (isShuttingDown()) { return; } // avoid crash if (isShuttingDown()) { return; } // avoid crash
if (! m_isAuthenticated) if (! m_isAuthenticated)
{ {

View File

@@ -25,29 +25,29 @@
#include <QNetworkReply> #include <QNetworkReply>
#include <QJsonDocument> #include <QJsonDocument>
// TODO:
// - JWT refresh
namespace BlackCore namespace BlackCore
{ {
namespace Afv namespace Afv
{ {
namespace Connection namespace Connection
{ {
//! A server connection
class ApiServerConnection : public QObject class ApiServerConnection : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
//! Server errors
enum ServerError enum ServerError
{ {
NoError NoError
}; };
//! Constructor
ApiServerConnection(const QString &address, QObject *parent = nullptr); ApiServerConnection(const QString &address, QObject *parent = nullptr);
bool isAuthenticated() const { return m_isAuthenticated; } bool isAuthenticated() const { return m_isAuthenticated; }
void connectTo(const QString &username, const QString &password, const QUuid &networkVersion); bool connectTo(const QString &username, const QString &password, const QUuid &networkVersion);
PostCallsignResponseDto addCallsign(const QString &callsign); PostCallsignResponseDto addCallsign(const QString &callsign);
void removeCallsign(const QString &callsign); void removeCallsign(const QString &callsign);
@@ -106,7 +106,7 @@ namespace BlackCore
QString m_password; QString m_password;
QUuid m_networkVersion; QUuid m_networkVersion;
QDateTime m_expiryLocalUtc; QDateTime m_expiryLocalUtc;
qint64 m_serverToUserOffset; qint64 m_serverToUserOffsetMs;
bool m_isAuthenticated = false; bool m_isAuthenticated = false;