136 lines
4.4 KiB
C++
136 lines
4.4 KiB
C++
#include "ubuntuoneauthenticator.h"
|
|
|
|
#include <time.h>
|
|
|
|
#include <QCoreApplication>
|
|
#include <QDateTime>
|
|
#include <QHostInfo>
|
|
#include <QStringList>
|
|
|
|
#include <qjson/parser.h>
|
|
|
|
#include "core/closure.h"
|
|
#include "core/logging.h"
|
|
#include "core/network.h"
|
|
#include "core/timeconstants.h"
|
|
|
|
namespace {
|
|
static const char* kUbuntuOneEndpoint =
|
|
"https://login.ubuntu.com/api/1.0/authentications";
|
|
static const char* kTokenNameTemplate = "Ubuntu One @ %1 [%2]";
|
|
static const char* kOAuthSSOFinishedEndpoint =
|
|
"https://one.ubuntu.com/oauth/sso-finished-so-get-tokens/";
|
|
static const char* kOAuthHeaderPrefix = "OAuth realm=\"\", ";
|
|
}
|
|
|
|
UbuntuOneAuthenticator::UbuntuOneAuthenticator(QObject* parent)
|
|
: QObject(parent),
|
|
network_(new NetworkAccessManager(this)),
|
|
success_(false) {}
|
|
|
|
void UbuntuOneAuthenticator::StartAuthorisation(const QString& email,
|
|
const QString& password) {
|
|
QUrl url(kUbuntuOneEndpoint);
|
|
url.addQueryItem("ws.op", "authenticate");
|
|
QString token_name = QString(kTokenNameTemplate).arg(
|
|
QHostInfo::localHostName(), QCoreApplication::applicationName());
|
|
url.addQueryItem("token_name", token_name);
|
|
|
|
QByteArray authentication =
|
|
QString(email + ":" + password).toAscii().toBase64();
|
|
QString authorisation =
|
|
QString("Basic %1").arg(QString::fromAscii(authentication));
|
|
|
|
QNetworkRequest request(url);
|
|
request.setRawHeader("Authorization", authorisation.toAscii());
|
|
request.setRawHeader("Accept", "application/json");
|
|
|
|
QNetworkReply* reply = network_->get(request);
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
SLOT(AuthorisationFinished(QNetworkReply*)), reply);
|
|
|
|
qLog(Debug) << url;
|
|
qLog(Debug) << authorisation;
|
|
}
|
|
|
|
void UbuntuOneAuthenticator::AuthorisationFinished(QNetworkReply* reply) {
|
|
reply->deleteLater();
|
|
|
|
QByteArray data = reply->readAll();
|
|
qLog(Debug) << data;
|
|
|
|
QJson::Parser parser;
|
|
bool ok = false;
|
|
QVariant json = parser.parse(data, &ok);
|
|
if (!ok) {
|
|
qLog(Error) << "Failed to authenticate to Ubuntu One:"
|
|
<< parser.errorString();
|
|
emit Finished();
|
|
return;
|
|
}
|
|
|
|
QVariantMap auth_info = json.toMap();
|
|
consumer_key_ = auth_info["consumer_key"].toString();
|
|
consumer_secret_ = auth_info["consumer_secret"].toString();
|
|
token_ = auth_info["token"].toString();
|
|
token_secret_ = auth_info["token_secret"].toString();
|
|
|
|
CopySSOTokens();
|
|
}
|
|
|
|
QByteArray UbuntuOneAuthenticator::GenerateAuthorisationHeader(
|
|
const QString& consumer_key, const QString& consumer_secret,
|
|
const QString& token, const QString& token_secret) {
|
|
typedef QPair<QString, QString> Param;
|
|
QString timestamp = QString::number(time(nullptr));
|
|
QList<Param> parameters;
|
|
parameters << Param("oauth_nonce", QString::number(qrand()))
|
|
<< Param("oauth_timestamp", timestamp)
|
|
<< Param("oauth_version", "1.0")
|
|
<< Param("oauth_consumer_key", consumer_key)
|
|
<< Param("oauth_token", token)
|
|
<< Param("oauth_signature_method", "PLAINTEXT");
|
|
qSort(parameters.begin(), parameters.end());
|
|
QStringList encoded_params;
|
|
for (const Param& p : parameters) {
|
|
encoded_params << QString("%1=%2").arg(p.first, p.second);
|
|
}
|
|
|
|
QString signing_key = consumer_secret + "&" + token_secret;
|
|
QByteArray signature = QUrl::toPercentEncoding(signing_key);
|
|
|
|
// Construct authorisation header
|
|
parameters << Param("oauth_signature", signature);
|
|
QStringList header_params;
|
|
for (const Param& p : parameters) {
|
|
header_params << QString("%1=\"%2\"").arg(p.first, p.second);
|
|
}
|
|
QString authorisation_header = header_params.join(", ");
|
|
authorisation_header.prepend(kOAuthHeaderPrefix);
|
|
|
|
return authorisation_header.toAscii();
|
|
}
|
|
|
|
QByteArray UbuntuOneAuthenticator::GenerateAuthorisationHeader() {
|
|
return GenerateAuthorisationHeader(consumer_key_, consumer_secret_, token_,
|
|
token_secret_);
|
|
}
|
|
|
|
void UbuntuOneAuthenticator::CopySSOTokens() {
|
|
QUrl url(kOAuthSSOFinishedEndpoint);
|
|
QNetworkRequest request(url);
|
|
request.setRawHeader("Authorization", GenerateAuthorisationHeader());
|
|
request.setRawHeader("Accept", "application/json");
|
|
|
|
QNetworkReply* reply = network_->get(request);
|
|
NewClosure(reply, SIGNAL(finished()), this,
|
|
SLOT(CopySSOTokensFinished(QNetworkReply*)), reply);
|
|
}
|
|
|
|
void UbuntuOneAuthenticator::CopySSOTokensFinished(QNetworkReply* reply) {
|
|
reply->deleteLater();
|
|
qLog(Debug) << reply->readAll();
|
|
success_ = true;
|
|
emit Finished();
|
|
}
|