Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ open standard [RFC 7519](https://tools.ietf.org/html/rfc7519).

Currently this implementation **only supports** the following algorithms:

Alg | Parameter Value Algorithm
----- | ------------------------------------
HS256 | HMAC using SHA-256 hash algorithm
HS384 | HMAC using SHA-384 hash algorithm
HS512 | HMAC using SHA-512 hash algorithm
Alg | Parameter Value Algorithm | Using library
----- | --------------------------------- | --------------
HS256 | HMAC using SHA-256 hash algorithm | Qt
HS384 | HMAC using SHA-384 hash algorithm | Qt
HS512 | HMAC using SHA-512 hash algorithm | Qt
RS256 | RSA using SHA-256 hash algorithm | QCA (optional)
RS384 | RSA using SHA-384 hash algorithm | QCA (optional)
RS512 | RSA using SHA-512 hash algorithm | QCA (optional)

### Include

Expand All @@ -30,10 +33,6 @@ The repository of this project includes examples that demonstrate the use of thi

* ```./examples/jwtverifier/``` : Example that shows how to validate a JWT with a given *secret*.

### Limitations

Currently, `QJsonWebToken` validator, can **only** validate tokens created by `QJsonWebToken` itself. This limitation is due to the usage of Qt's [QJsonDocument API](http://doc.qt.io/qt-5/qjsondocument.html), see [this issue for further explanation](https://github.com/juangburgos/QJsonWebToken/issues/3#issuecomment-333056575).

### License

MIT
Expand Down
107 changes: 86 additions & 21 deletions examples/jwtcreator/dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,36 @@
#include <QDateTime>

Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
QDialog(parent),
ui(new Ui::Dialog),
hsKey(QJsonWebKey::fromOctet("mydirtysecret")),
rsKey(nullptr)
{
ui->setupUi(this);
ui->setupUi(this);
// set some tooltips
ui->pushRemoveClaim->setToolTip("To remove a claim you just need to define the <b>Claim Type<\b>");
ui->pushRemoveClaim->setToolTipDuration(3500);
// set default secret
ui->lineSecret->setText("mydirtysecret");
m_jwtObj.setSecret("mydirtysecret");
ui->plainTextEditKey->setPlainText(QString::fromUtf8(hsKey->toJson()));
m_jwtObj.setKey(hsKey);
// set a default payload
m_jwtObj.appendClaim("iss", "juangburgos");
m_jwtObj.appendClaim("iat", QString::number(QDateTime::currentDateTime().toTime_t()));
m_jwtObj.appendClaim("exp", QString::number(QDateTime::currentDateTime().addDays(7).toTime_t()));
m_jwtObj.appendClaim("iat", static_cast<qint64>(QDateTime::currentDateTime().toTime_t()));
m_jwtObj.appendClaim("exp", static_cast<qint64>(QDateTime::currentDateTime().addDays(7).toTime_t()));
m_jwtObj.appendClaim("aud", "everybody");
m_jwtObj.appendClaim("sub", "hey there");
// set current value to views
ui->plainTextClaims->setPlainText(m_jwtObj.getPayloadQStr());
// setup combobox (exec at the end because it calls slot)
ui->comboAlgorithm->addItems(QJsonWebToken::supportedAlgorithms());
#ifdef USE_QCA
rsKey = QJsonWebKey::generateRSAPrivateKey(2048);
#endif // USE_QCA
}

Dialog::~Dialog()
{
delete ui;
delete ui;
}

void Dialog::on_pushAddClaim_clicked()
Expand Down Expand Up @@ -79,28 +84,88 @@ void Dialog::on_pushRemoveClaim_clicked()

void Dialog::on_comboAlgorithm_currentIndexChanged(const QString &arg1)
{
if (!arg1.startsWith(m_jwtObj.getAlgorithmStr().left(2)))
{
// change algorithm
if (arg1.startsWith("HS"))
{
m_jwtObj.setKey(hsKey);
ui->plainTextEditKey->blockSignals(true);
ui->plainTextEditKey->setPlainText(QString::fromUtf8(hsKey->toJson()));
ui->plainTextEditKey->blockSignals(false);
}
#ifdef USE_QCA
else if (arg1.startsWith("RS"))
{
if (rsKey.isNull())
{
rsKey = QJsonWebKey::generateRSAPrivateKey(2048);
}
m_jwtObj.setKey(rsKey);
ui->plainTextEditKey->blockSignals(true);
ui->plainTextEditKey->setPlainText(!rsKey.isNull() ? QString::fromUtf8(rsKey->toJson()) : QString());
ui->plainTextEditKey->blockSignals(false);
}
#endif // USE_QCA
}
// set new secret
m_jwtObj.setAlgorithmStr(arg1);
// show new jwt
ui->plainTextSignedJwt->setPlainText(m_jwtObj.getToken());
}

void Dialog::on_lineSecret_textChanged(const QString &arg1)
void Dialog::on_plainTextEditKey_textChanged()
{
// set new secret
m_jwtObj.setSecret(ui->lineSecret->text());
// show new jwt
ui->plainTextSignedJwt->setPlainText(m_jwtObj.getToken());
QString text = ui->plainTextEditKey->toPlainText();
if (ui->comboAlgorithm->currentText().startsWith("HS"))
{
hsKey = QJsonWebKey::fromJsonWebKey(text.toUtf8());
// set new secret
m_jwtObj.setKey(hsKey);
}
#ifdef USE_QCA
else if (ui->comboAlgorithm->currentText().startsWith("RS"))
{
rsKey = QJsonWebKey::fromJsonWebKey(text.toUtf8());
// set new secret
m_jwtObj.setKey(rsKey);
}
#endif // USE_QCA
// show new jwt
ui->plainTextSignedJwt->setPlainText(m_jwtObj.getToken());
}

void Dialog::on_pushRandom_clicked()
{
// set random secret
m_jwtObj.setRandomSecret();
// set random secret in lineedit
ui->lineSecret->blockSignals(true);
ui->lineSecret->setText(m_jwtObj.getSecret());
ui->lineSecret->blockSignals(false);
// show new jwt
ui->plainTextSignedJwt->setPlainText(m_jwtObj.getToken());
if (ui->comboAlgorithm->currentText().startsWith("HS"))
{
// set random secret
int randLength = 10;
QByteArray randAlphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
QByteArray secret;
secret.resize(randLength);
for (int i = 0; i < randLength; ++i)
{
secret[i] = randAlphanum.at(rand() % (randAlphanum.length() - 1));
}
hsKey = QJsonWebKey::fromOctet(secret);
m_jwtObj.setKey(hsKey);
// set random secret in lineedit
ui->plainTextEditKey->blockSignals(true);
ui->plainTextEditKey->setPlainText(QString::fromUtf8(hsKey->toJson()));
ui->plainTextEditKey->blockSignals(false);
}
#ifdef USE_QCA
else if (ui->comboAlgorithm->currentText().startsWith("RS"))
{
rsKey = QJsonWebKey::generateRSAPrivateKey(2048);
m_jwtObj.setKey(rsKey);
// set random secret in lineedit
ui->plainTextEditKey->blockSignals(true);
ui->plainTextEditKey->setPlainText(!rsKey.isNull() ? QString::fromUtf8(rsKey->toJson()) : QString());
ui->plainTextEditKey->blockSignals(false);
}
#endif // USE_QCA
// show new jwt
ui->plainTextSignedJwt->setPlainText(m_jwtObj.getToken());
}
4 changes: 3 additions & 1 deletion examples/jwtcreator/dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ private slots:

void on_comboAlgorithm_currentIndexChanged(const QString &arg1);

void on_lineSecret_textChanged(const QString &arg1);
void on_plainTextEditKey_textChanged();

void on_pushRandom_clicked();

private:
Ui::Dialog *ui;
QSharedPointer<QJsonWebKey> hsKey;
QSharedPointer<QJsonWebKey> rsKey;
};

#endif // DIALOG_H
94 changes: 51 additions & 43 deletions examples/jwtcreator/dialog.ui
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>564</width>
<height>604</height>
<height>694</height>
</rect>
</property>
<property name="sizePolicy">
Expand Down Expand Up @@ -99,54 +99,62 @@
<string>JWT Signer</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Secret : </string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="lineSecret"/>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="pushRandom">
<property name="text">
<string>Random</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Algorithm : </string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QComboBox" name="comboAlgorithm">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0" colspan="6">
<item row="4" column="0" colspan="4">
<widget class="QPlainTextEdit" name="plainTextSignedJwt">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>JWK</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="plainTextEditKey"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Algorithm : </string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QComboBox" name="comboAlgorithm">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QPushButton" name="pushRandom">
<property name="text">
<string>Random</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
Expand Down
17 changes: 17 additions & 0 deletions examples/jwtcreator/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,27 @@

#include "dialog.h"
#include <QApplication>
#include <QDebug>
#include <QDir>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

#ifdef USE_QCA
QDir dir(QApplication::applicationDirPath());
dir.cd("plugins");
QApplication::addLibraryPath(dir.absolutePath());

QCA::Initializer init;
Q_UNUSED(init);

if (!QCA::isSupported("pkey") || !QCA::PKey::supportedIOTypes().contains(QCA::PKey::RSA))
{
qDebug() << "RSA not supported.";
}
#endif

Dialog w;
w.show();

Expand Down
25 changes: 15 additions & 10 deletions examples/jwtverifier/dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
ui->setupUi(this);
// setup initial button color
ui->pushStatus->setStyleSheet("background-color: #ff8080; color: black; font: bold;");
}

Dialog::~Dialog()
{
delete ui;
delete ui;
}

void Dialog::on_plainTextEncoded_textChanged()
Expand All @@ -34,16 +34,16 @@ void Dialog::on_plainTextEncoded_textChanged()
ui->plainTextPayload->setPlainText(QObject::trUtf8("ERROR : token must have the format xxxx.yyyyy.zzzzz"));
return;
}
QString strSecret = ui->lineEditSecret->text();
if (strSecret.isEmpty())
QString key = ui->plainTextEditKey->toPlainText();
if (key.isEmpty())
{
// show error
ui->plainTextHeader->setPlainText(QObject::trUtf8("ERROR : secret must be non-empty"));
ui->plainTextPayload->setPlainText(QObject::trUtf8("ERROR : secret must be non-empty"));
ui->plainTextHeader->setPlainText(QObject::trUtf8("ERROR : key must be non-empty"));
ui->plainTextPayload->setPlainText(QObject::trUtf8("ERROR : key must be non-empty"));
return;
}
// set token and secret
QJsonWebToken token = QJsonWebToken::fromTokenAndSecret(strToken, strSecret);
QJsonWebToken token = QJsonWebToken::fromTokenAndKey(strToken, QJsonWebKey::fromJsonWebKey(key.toUtf8()));
// get decoded header and payload
QString strHeader = token.getHeaderQStr();
QString strPayload = token.getPayloadQStr();
Expand All @@ -63,7 +63,12 @@ void Dialog::on_plainTextEncoded_textChanged()

}

void Dialog::on_lineEditSecret_textChanged(const QString &arg1)
void Dialog::on_checkBoxIsOctet_stateChanged()
{
on_plainTextEncoded_textChanged();
}

void Dialog::on_plainTextEditKey_textChanged()
{
on_plainTextEncoded_textChanged();
}
Loading