somewhat working

This commit is contained in:
Michael Zanetti 2018-08-14 17:13:17 +02:00
parent 833e59550c
commit db21e6cdf3
8 changed files with 96 additions and 38 deletions

3
.gitmodules vendored
View File

@ -7,3 +7,6 @@
[submodule "qmqtt"]
path = qmqtt
url = https://github.com/emqtt/qmqtt.git
[submodule "nymea-remoteproxy"]
path = nymea-remoteproxy
url = git@gitlab.guh.io:cloud/nymea-remoteproxy.git

View File

@ -23,6 +23,7 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
settings.beginGroup("cloud");
m_username = settings.value("username").toString();
m_accessToken = settings.value("accessToken").toByteArray();
m_accessTokenExpiry = settings.value("accessTokenExpiry").toDateTime();
m_idToken = settings.value("idToken").toByteArray();
m_refreshToken = settings.value("refreshToken").toByteArray();
@ -30,6 +31,9 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
m_secretKey = settings.value("secretKey").toByteArray();
m_sessionToken = settings.value("sessionToken").toByteArray();
// if (m_accessTokenExpiry < QDateTime::currentDateTime() && !m_refreshToken.isEmpty()) {
refreshAccessToken();
// }
}
bool AWSClient::isLoggedIn() const
@ -90,12 +94,14 @@ void AWSClient::login(const QString &username, const QString &password)
QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
m_accessToken = authenticationResult.value("AccessToken").toByteArray();
m_accessTokenExpiry = QDateTime::currentDateTime().addSecs(authenticationResult.value("ExpiresIn").toInt());
m_idToken = authenticationResult.value("IdToken").toByteArray();
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
QSettings settings;
settings.beginGroup("cloud");
settings.setValue("accessToken", m_accessToken);
settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
settings.setValue("idToken", m_idToken);
settings.setValue("refreshToken", m_refreshToken);
@ -252,7 +258,7 @@ void AWSClient::connectMQTT()
void AWSClient::postToMQTT()
{
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com";
QString topic = "850593e9-f2ab-4e89-913a-16f848d48867/eu-west-1:88c8b0f1-3f26-46cb-81f3-ccc37dcb543a/";
QString topic = "850593e9-f2ab-4e89-913a-16f848d48867/eu-west-1:88c8b0f1-3f26-46cb-81f3-ccc37dcb543a/proxy";
// This is somehow broken in AWS...
// The Signature needs to be created with having the topic percentage-encoded twice
@ -333,3 +339,68 @@ QByteArray AWSClient::accessToken() const
return m_accessToken;
}
void AWSClient::refreshAccessToken()
{
QUrl url("https://cognito-idp.eu-west-1.amazonaws.com/");
QUrlQuery query;
query.addQueryItem("Action", "InitiateAuth");
query.addQueryItem("Version", "2016-04-18");
url.setQuery(query);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-amz-json-1.0");
request.setRawHeader("Host", "cognito-idp.eu-west-1.amazonaws.com");
request.setRawHeader("X-Amz-Target", "AWSCognitoIdentityProviderService.InitiateAuth");
QVariantMap params;
params.insert("AuthFlow", "REFRESH_TOKEN_AUTH");
// params.insert("AuthFlow", "USER_PASSWORD_AUTH");
params.insert("ClientId", clientId);
QVariantMap authParams;
authParams.insert("REFRESH_TOKEN", m_refreshToken);
// authParams.insert("USERNAME", m_username);
// authParams.insert("PASSWORD", "H22*xgemmmmm");
params.insert("AuthParameters", authParams);
QJsonDocument jsonDoc = QJsonDocument::fromVariant(params);
QByteArray payload = jsonDoc.toJson(QJsonDocument::Compact);
qDebug() << "Refreshing AWS token for user:" << m_username << qUtf8Printable(payload);
QNetworkReply *reply = m_nam->post(request, payload);
connect(reply, &QNetworkReply::finished, this, [this, reply]() {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
qWarning() << "Error logging in to aws:" << reply->error() << reply->errorString();
return;
}
QByteArray data = reply->readAll();
QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) {
qWarning() << "Failed to parse AWS login response" << error.errorString();
return;
}
// QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
// m_accessToken = authenticationResult.value("AccessToken").toByteArray();
// m_accessTokenExpiry = QDateTime::currentDateTime().addSecs(authenticationResult.value("ExpiresIn").toInt());
// m_idToken = authenticationResult.value("IdToken").toByteArray();
// m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
// QSettings settings;
// settings.beginGroup("cloud");
// settings.setValue("accessToken", m_accessToken);
// settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
// settings.setValue("idToken", m_idToken);
// settings.setValue("refreshToken", m_refreshToken);
qDebug() << "AWS login successful" << qUtf8Printable(jsonDoc.toJson(QJsonDocument::Indented));
emit isLoggedInChanged();
});
}

View File

@ -39,6 +39,7 @@ signals:
void devicesFetched(QList<AWSDevice> devices);
private:
void refreshAccessToken();
void getCredentialsForIdentity(const QString &identityId);
void connectMQTT();
@ -47,6 +48,7 @@ private:
QString m_username;
QByteArray m_accessToken;
QDateTime m_accessTokenExpiry;
QByteArray m_idToken;
QByteArray m_refreshToken;

View File

@ -1,12 +1,15 @@
#include "cloudtransport.h"
#include "qmqtt.h"
#include "awsclient.h"
#include "remoteproxyconnection.h"
using namespace remoteproxyclient;
CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
NymeaTransportInterface(parent),
m_awsClient(awsClient)
{
m_remoteproxyConnection = new RemoteProxyConnection(QUuid::createUuid(), "nymea:app", RemoteProxyConnection::ConnectionTypeWebSocket, this);
}
QStringList CloudTransport::supportedSchemes() const
@ -17,34 +20,10 @@ QStringList CloudTransport::supportedSchemes() const
void CloudTransport::connect(const QUrl &url)
{
qDebug() << "should connect to" << url;
QString date = QDateTime::currentDateTime().toString("yyyyMMddThhmmssZ");
QString region = "eu-west-1";
QString service = "iotdevicegateway";
QString credentialScope = date + '/' + region + '/' + service + '/' + "aws4_request";
QString algorithm = "AWS4-HMAC-SHA256";
QString canonicalQuerystring = "X-Amz-Algorithm=" + algorithm;
m_awsClient->postToMQTT();
// canonicalQuerystring += "&X-Amz-Credential=" + QByteArray(credentials.accessKeyId + '/' + credentialScope).toPercentageEncoded();
// '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
m_remoteproxyConnection->connectServer(QHostAddress("127.0.0.1"), 1212);
QString requestUrl = "wss://a2addxakg5juii.iot.eu-west-1.amazonaws.com/mqtt?" + canonicalQuerystring;
m_mqttClient = new QMQTT::Client(requestUrl, 443, QWebSocketProtocol::VersionLatest, true, this);
QObject::connect(m_mqttClient, &QMQTT::Client::connected, this, [](){
qDebug() << "MQTT connected";
});
QObject::connect(m_mqttClient, &QMQTT::Client::disconnected, this, []() {
qDebug() << "MQTT disconnected";
});
QObject::connect(m_mqttClient, &QMQTT::Client::error, this, [](QMQTT::ClientError error) {
qDebug() << "MQTT error" << error << QMQTT::ClientError::SocketHostNotFoundError;
});
m_mqttClient->setUsername("michael.zanetti@guh.io");
m_mqttClient->setPassword("H22*gemmmmm");
m_mqttClient->setClientId("8rjhfdlf9jf1suok2jcrltd6v");
m_mqttClient->connectToHost();
}
void CloudTransport::disconnect()

View File

@ -5,10 +5,10 @@
#include <QObject>
namespace QMQTT {
class Client;
}
class AWSClient;
namespace remoteproxyclient {
class RemoteProxyConnection;
}
class CloudTransport : public NymeaTransportInterface
{
@ -24,8 +24,8 @@ public:
void sendData(const QByteArray &data) override;
private:
QMQTT::Client *m_mqttClient = nullptr;
AWSClient *m_awsClient = nullptr;
remoteproxyclient::RemoteProxyConnection *m_remoteproxyConnection = nullptr;
};
#endif // CLOUDTRANSPORT_H

View File

@ -18,8 +18,8 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef JSONRPCCLIENT_H
#define JSONRPCCLIENT_H
#ifndef NYMEAJSONRPCCLIENT_H
#define NYMEAJSONRPCCLIENT_H
#include <QObject>
#include <QVariantMap>
@ -157,4 +157,4 @@ private:
};
#endif // JSONRPCCLIENT_H
#endif // NYMEAJSONRPCCLIENT_H

View File

@ -12,8 +12,9 @@ include(../config.pri)
}
DEFINES += QT_STATIC
include(../qmqtt/src/mqtt/mqtt.pri)
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \
connection/sigv4utils.h
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
include(../nymea-remoteproxy/libnymea-remoteproxyclient/libnymea-remoteproxyclient.pri)
QT -= gui
QT += network websockets bluetooth
@ -89,6 +90,7 @@ HEADERS += \
connection/tcpsockettransport.h \
connection/bluetoothtransport.h \
connection/awsclient.h \
connection/sigv4utils.h \
devicemanager.h \
jsonrpc/jsontypes.h \
jsonrpc/jsonrpcclient.h \

1
nymea-remoteproxy Submodule

@ -0,0 +1 @@
Subproject commit c2c3304a558a434115c49e168155da8eba81cd98