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"] [submodule "qmqtt"]
path = qmqtt path = qmqtt
url = https://github.com/emqtt/qmqtt.git 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"); settings.beginGroup("cloud");
m_username = settings.value("username").toString(); m_username = settings.value("username").toString();
m_accessToken = settings.value("accessToken").toByteArray(); m_accessToken = settings.value("accessToken").toByteArray();
m_accessTokenExpiry = settings.value("accessTokenExpiry").toDateTime();
m_idToken = settings.value("idToken").toByteArray(); m_idToken = settings.value("idToken").toByteArray();
m_refreshToken = settings.value("refreshToken").toByteArray(); m_refreshToken = settings.value("refreshToken").toByteArray();
@ -30,6 +31,9 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent)
m_secretKey = settings.value("secretKey").toByteArray(); m_secretKey = settings.value("secretKey").toByteArray();
m_sessionToken = settings.value("sessionToken").toByteArray(); m_sessionToken = settings.value("sessionToken").toByteArray();
// if (m_accessTokenExpiry < QDateTime::currentDateTime() && !m_refreshToken.isEmpty()) {
refreshAccessToken();
// }
} }
bool AWSClient::isLoggedIn() const 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(); QVariantMap authenticationResult = jsonDoc.toVariant().toMap().value("AuthenticationResult").toMap();
m_accessToken = authenticationResult.value("AccessToken").toByteArray(); m_accessToken = authenticationResult.value("AccessToken").toByteArray();
m_accessTokenExpiry = QDateTime::currentDateTime().addSecs(authenticationResult.value("ExpiresIn").toInt());
m_idToken = authenticationResult.value("IdToken").toByteArray(); m_idToken = authenticationResult.value("IdToken").toByteArray();
m_refreshToken = authenticationResult.value("RefreshToken").toByteArray(); m_refreshToken = authenticationResult.value("RefreshToken").toByteArray();
QSettings settings; QSettings settings;
settings.beginGroup("cloud"); settings.beginGroup("cloud");
settings.setValue("accessToken", m_accessToken); settings.setValue("accessToken", m_accessToken);
settings.setValue("accessTokenExpiry", m_accessTokenExpiry);
settings.setValue("idToken", m_idToken); settings.setValue("idToken", m_idToken);
settings.setValue("refreshToken", m_refreshToken); settings.setValue("refreshToken", m_refreshToken);
@ -252,7 +258,7 @@ void AWSClient::connectMQTT()
void AWSClient::postToMQTT() void AWSClient::postToMQTT()
{ {
QString host = "a2addxakg5juii.iot.eu-west-1.amazonaws.com"; 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... // This is somehow broken in AWS...
// The Signature needs to be created with having the topic percentage-encoded twice // The Signature needs to be created with having the topic percentage-encoded twice
@ -333,3 +339,68 @@ QByteArray AWSClient::accessToken() const
return m_accessToken; 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); void devicesFetched(QList<AWSDevice> devices);
private: private:
void refreshAccessToken();
void getCredentialsForIdentity(const QString &identityId); void getCredentialsForIdentity(const QString &identityId);
void connectMQTT(); void connectMQTT();
@ -47,6 +48,7 @@ private:
QString m_username; QString m_username;
QByteArray m_accessToken; QByteArray m_accessToken;
QDateTime m_accessTokenExpiry;
QByteArray m_idToken; QByteArray m_idToken;
QByteArray m_refreshToken; QByteArray m_refreshToken;

View File

@ -1,12 +1,15 @@
#include "cloudtransport.h" #include "cloudtransport.h"
#include "qmqtt.h" #include "awsclient.h"
#include "remoteproxyconnection.h"
using namespace remoteproxyclient;
CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent): CloudTransport::CloudTransport(AWSClient *awsClient, QObject *parent):
NymeaTransportInterface(parent), NymeaTransportInterface(parent),
m_awsClient(awsClient) m_awsClient(awsClient)
{ {
m_remoteproxyConnection = new RemoteProxyConnection(QUuid::createUuid(), "nymea:app", RemoteProxyConnection::ConnectionTypeWebSocket, this);
} }
QStringList CloudTransport::supportedSchemes() const QStringList CloudTransport::supportedSchemes() const
@ -17,34 +20,10 @@ QStringList CloudTransport::supportedSchemes() const
void CloudTransport::connect(const QUrl &url) void CloudTransport::connect(const QUrl &url)
{ {
qDebug() << "should connect to" << url; qDebug() << "should connect to" << url;
QString date = QDateTime::currentDateTime().toString("yyyyMMddThhmmssZ"); m_awsClient->postToMQTT();
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;
// canonicalQuerystring += "&X-Amz-Credential=" + QByteArray(credentials.accessKeyId + '/' + credentialScope).toPercentageEncoded(); m_remoteproxyConnection->connectServer(QHostAddress("127.0.0.1"), 1212);
// '&X-Amz-Security-Token=' + encodeURIComponent(credentials.sessionToken);
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() void CloudTransport::disconnect()

View File

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

View File

@ -18,8 +18,8 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef JSONRPCCLIENT_H #ifndef NYMEAJSONRPCCLIENT_H
#define JSONRPCCLIENT_H #define NYMEAJSONRPCCLIENT_H
#include <QObject> #include <QObject>
#include <QVariantMap> #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 DEFINES += QT_STATIC
include(../qmqtt/src/mqtt/mqtt.pri) include(../qmqtt/src/mqtt/mqtt.pri)
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \ HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
connection/sigv4utils.h
include(../nymea-remoteproxy/libnymea-remoteproxyclient/libnymea-remoteproxyclient.pri)
QT -= gui QT -= gui
QT += network websockets bluetooth QT += network websockets bluetooth
@ -89,6 +90,7 @@ HEADERS += \
connection/tcpsockettransport.h \ connection/tcpsockettransport.h \
connection/bluetoothtransport.h \ connection/bluetoothtransport.h \
connection/awsclient.h \ connection/awsclient.h \
connection/sigv4utils.h \
devicemanager.h \ devicemanager.h \
jsonrpc/jsontypes.h \ jsonrpc/jsontypes.h \
jsonrpc/jsonrpcclient.h \ jsonrpc/jsonrpcclient.h \

1
nymea-remoteproxy Submodule

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