Commit e3481f18 authored by Jesus Fernandez's avatar Jesus Fernandez

QtOAuth Refactor

parent f0ba3c9a
INCLUDEPATH += $$IN_PWD/QtOAuth
DEPENDPATH += $$OUT_PWD/../QtOAuth
win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../QtOAuth/release/ -lQtOAuth
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../QtOAuth/debug/ -lQtOAuth
win32:CONFIG(release, debug|release): {
DESTDIR = $$OUT_PWD/../../release
LIBS += $$OUT_PWD/../../release/QtOAuth.lib
} else:win32:CONFIG(debug, debug|release): {
DESTDIR = $$OUT_PWD/../../debug
LIBS += $$OUT_PWD/../../debug/QtOAuth.lib
}
else:unix: LIBS += -L$$OUT_PWD/../../QtOAuth/ -lQtOAuth
......@@ -4,3 +4,6 @@ SUBDIRS += \
QtOAuth \
tests \
examples
tests.depends = QtOAuth
examples.depends = QtOAuth
......@@ -2,8 +2,16 @@ TEMPLATE = lib
TARGET = QtOAuth
INCLUDEPATH += .
win32:CONFIG(release, debug|release): {
DESTDIR = $$OUT_PWD/../release
} else:win32:CONFIG(debug, debug|release): {
DESTDIR = $$OUT_PWD/../debug
}
QT += core core-private network
DEFINES += OAUTH_LIBRARY
# Input
HEADERS += qabstractoauth.h \
qabstractoauth2.h \
......
......@@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
class QNetworkAccessManager;
class QAbstractOAuth2Private : public QAbstractOAuthPrivate
class OAUTH_EXPORT QAbstractOAuth2Private : public QAbstractOAuthPrivate
{
Q_DECLARE_PUBLIC(QAbstractOAuth2)
......@@ -75,9 +75,30 @@ public:
QAbstractOAuth2Private(QNetworkAccessManager *manager);
~QAbstractOAuth2Private();
QString verifier;
static QString generateRandomState();
QAbstractOAuth2::Credential consumer;
QAbstractOAuth2::Credential token;
QString scope;
QString apiKey;
QString userAgent = "qoauth/0.1";
struct OAuth2KeyString
{
static const QString accessToken;
static const QString clientId;
static const QString code;
static const QString error;
static const QString errorDescription;
static const QString errorUri;
static const QString expiresIn;
static const QString grantType;
static const QString redirectUri;
static const QString refreshToken;
static const QString responseType;
static const QString scope;
static const QString state;
static const QString tokenType;
};
};
QT_END_NAMESPACE
......
......@@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE
class QUrlQuery;
class Q_AUTOTEST_EXPORT QAbstractOAuthPrivate : public QObjectPrivate
class OAUTH_EXPORT QAbstractOAuthPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QAbstractOAuth)
......@@ -79,18 +79,14 @@ public:
void setStatus(QAbstractOAuth::Status status);
QOAuthTokenPair clientId;
QString redirectUri;
QOAuthTokenPair token;
QOAuthTokenPair accessToken;
QUrl requestTokenUrl;
QUrl authorizationGrantUrl;
QUrl authenticateUrl;
QVariantMap extraTokens;
QAbstractOAuth::Status status;
QNetworkAccessManager::Operation operation;
QScopedPointer<QAbstractOAuthReplyHandler> replyHandler;
QScopedPointer<QOAuthOobReplyHandler> defaultReplyHandler;
QNetworkAccessManager *networkAccessManager;
QAbstractOAuth::ModifyParametersFunction modifyParametersFunction;
static QUrlQuery createQuery(const QVariantMap &parameters);
};
......
......@@ -65,7 +65,7 @@
QT_BEGIN_NAMESPACE
class QOAuth1Private : public QAbstractOAuthPrivate
class OAUTH_EXPORT QOAuth1Private : public QAbstractOAuthPrivate
{
Q_DECLARE_PUBLIC(QOAuth1)
......@@ -82,24 +82,41 @@ public:
void _q_tokensReceived(const QVariantMap &tokens);
void appendCommonHeaders(QVariantMap *headers);
void appendSignature(QVariantMap *headers,
void appendSignature(QAbstractOAuth::Stage stage,
QVariantMap *headers,
const QUrl &url,
QNetworkAccessManager::Operation operation,
const QVariantMap parameters);
QNetworkReply *requestToken(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QOAuthTokenPair &token,
const QOAuth1::Credential &token,
const QVariantMap &additionalParameters);
QNetworkReply *requestAuthorizationGrant(QNetworkAccessManager::Operation operation,
const QUrl &url,
const QVariantMap &additionalParameters);
QAbstractOAuth::SignatureMethod signatureMethod;
QUrl requestTokenUrl;
QUrl authorizationGrantUrl;
QOAuth1::Credential clientCredentials;
QOAuth1::Credential token;
QOAuth1::SignatureMethod signatureMethod = QOAuth1::SignatureMethod::Hmac_Sha1;
const QString oauthVersion = QStringLiteral("1.0");
QString signatureMethodString() const;
static QString operationName(QNetworkAccessManager::Operation op);
struct OAuth1KeyString
{
static const QString oauthCallback;
static const QString oauthCallbackConfirmed;
static const QString oauthConsumerKey;
static const QString oauthNonce;
static const QString oauthSignature;
static const QString oauthSignatureMethod;
static const QString oauthTimestamp;
static const QString oauthToken;
static const QString oauthTokenSecret;
static const QString oauthVerifier;
static const QString oauthVersion;
};
};
QT_END_NAMESPACE
......
......@@ -62,16 +62,18 @@
QT_BEGIN_NAMESPACE
class QOAuth2AuthorizationCodeFlowPrivate : public QAbstractOAuth2Private
class OAUTH_EXPORT QOAuth2AuthorizationCodeFlowPrivate : public QAbstractOAuth2Private
{
Q_DECLARE_PUBLIC(QOAuth2AuthorizationCodeFlow)
public:
QOAuth2AuthorizationCodeFlowPrivate(QNetworkAccessManager *manager, quint16 port);
void handleCallback(const QVariantMap &data);
void handleCallback(const QVariantMap &data, const QString state);
void accessTokenRequestFinished();
private:
QUrl accessTokenUrl;
QString tokenType;
QDateTime expiresAt;
QString refreshToken;
......
......@@ -59,7 +59,7 @@
QT_BEGIN_NAMESPACE
class QOAuth2ImplicitGrantFlowPrivate : public QAbstractOAuth2Private
class OAUTH_EXPORT QOAuth2ImplicitGrantFlowPrivate : public QAbstractOAuth2Private
{
Q_DECLARE_PUBLIC(QOAuth2ImplicitGrantFlow)
......
......@@ -61,7 +61,7 @@
QT_BEGIN_NAMESPACE
class QOAuthHttpServerReplyHandlerPrivate : public QObjectPrivate
class OAUTH_EXPORT QOAuthHttpServerReplyHandlerPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QOAuthHttpServerReplyHandler)
......
......@@ -58,10 +58,10 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_METATYPE(QAbstractOAuth::Error)
QAbstractOAuthPrivate::QAbstractOAuthPrivate(QNetworkAccessManager *manager)
: status(QAbstractOAuth::Status::NotAuthenticated)
, replyHandler(nullptr)
, defaultReplyHandler(new QOAuthOobReplyHandler)
, networkAccessManager(manager)
: status(QAbstractOAuth::Status::NotAuthenticated),
replyHandler(nullptr),
defaultReplyHandler(new QOAuthOobReplyHandler),
networkAccessManager(manager)
{
Q_ASSERT(manager);
}
......@@ -86,11 +86,12 @@ QUrlQuery QAbstractOAuthPrivate::createQuery(const QVariantMap &parameters)
return query;
}
//QAbstractOAuth::QAbstractOAuth(QObject *parent)
// : QObject(*new QAbstractOAuthPrivate, parent)
//{
// qRegisterMetaType<QAbstractOAuth::Error>();
//}
QAbstractOAuth::Credential::Credential()
{}
QAbstractOAuth::Credential::Credential(const QString &credentialKey)
: key(credentialKey)
{}
QAbstractOAuth::QAbstractOAuth(QAbstractOAuthPrivate &dd, QObject *parent)
: QObject(dd, parent)
......@@ -107,48 +108,18 @@ QAbstractOAuth::Status QAbstractOAuth::status() const
return d->status;
}
QUrl QAbstractOAuth::requestTokenUrl() const
{
Q_D(const QAbstractOAuth);
return d->requestTokenUrl;
}
void QAbstractOAuth::setRequestTokenUrl(const QUrl &url)
{
Q_D(QAbstractOAuth);
if (d->requestTokenUrl != url) {
d->requestTokenUrl = url;
Q_EMIT requestTokenUrlChanged();
}
}
QUrl QAbstractOAuth::authorizationGrantUrl() const
QUrl QAbstractOAuth::authorizeUrl() const
{
Q_D(const QAbstractOAuth);
return d->authorizationGrantUrl;
return d->authenticateUrl;
}
void QAbstractOAuth::setAuthorizationGrantUrl(const QUrl &url)
void QAbstractOAuth::setAuthorizeUrl(const QUrl &url)
{
Q_D(QAbstractOAuth);
if (d->authorizationGrantUrl != url) {
d->authorizationGrantUrl = url;
Q_EMIT authorizationGrantUrlChanged();
}
}
QOAuthTokenPair QAbstractOAuth::clientId() const
{
Q_D(const QAbstractOAuth);
return d->clientId;
}
void QAbstractOAuth::setClientId(const QOAuthTokenPair &value)
{
Q_D(QAbstractOAuth);
if (d->clientId != value) {
d->clientId = value;
emit clientIdChanged(value);
if (d->authenticateUrl != url) {
d->authenticateUrl = url;
Q_EMIT authorizeUrlChanged(url);
}
}
......@@ -161,21 +132,6 @@ void QAbstractOAuth::setStatus(QAbstractOAuth::Status status)
}
}
QNetworkAccessManager::Operation QAbstractOAuth::operation() const
{
Q_D(const QAbstractOAuth);
return d->operation;
}
void QAbstractOAuth::setOperation(QNetworkAccessManager::Operation operation)
{
Q_D(QAbstractOAuth);
if (d->operation != operation) {
d->operation = operation;
Q_EMIT operationChanged();
}
}
QAbstractOAuthReplyHandler *QAbstractOAuth::replyHandler() const
{
Q_D(const QAbstractOAuth);
......@@ -188,24 +144,17 @@ void QAbstractOAuth::setReplyHandler(QAbstractOAuthReplyHandler *handler)
d->replyHandler.reset(handler);
}
QOAuthTokenPair QAbstractOAuth::token() const
QAbstractOAuth::ModifyParametersFunction QAbstractOAuth::modifyParametersFunction() const
{
Q_D(const QAbstractOAuth);
return d->token;
return d->modifyParametersFunction;
}
void QAbstractOAuth::setToken(const QOAuthTokenPair &token)
void QAbstractOAuth::setModifyParametersFunction(
const QAbstractOAuth::ModifyParametersFunction &modifyParametersFunction)
{
Q_D(QAbstractOAuth);
if (d->token != token) {
d->token = token;
Q_EMIT tokenChanged(token);
}
}
void QAbstractOAuth::setToken(const QString &token, const QString &secret)
{
setToken(qMakePair(token, secret));
d->modifyParametersFunction = modifyParametersFunction;
}
QVariantMap QAbstractOAuth::extraTokens() const
......@@ -224,3 +173,4 @@ QString QAbstractOAuth::callback() const
QT_END_NAMESPACE
#endif // QT_NO_HTTP
......@@ -49,10 +49,15 @@
#include <QtNetwork/qnetworkaccessmanager.h>
QT_BEGIN_NAMESPACE
#include <functional>
#if defined(OAUTH_LIBRARY)
# define OAUTH_EXPORT Q_DECL_EXPORT
#else
# define OAUTH_EXPORT Q_DECL_IMPORT
#endif
typedef QPair<QString, QString> QOAuthTokenPair;
Q_DECLARE_METATYPE(QOAuthTokenPair)
QT_BEGIN_NAMESPACE
class QUrl;
class QByteArray;
......@@ -61,66 +66,54 @@ class QNetworkRequest;
class QAbstractOAuthReplyHandler;
class QAbstractOAuthPrivate;
class Q_NETWORK_EXPORT QAbstractOAuth : public QObject
class OAUTH_EXPORT QAbstractOAuth : public QObject
{
Q_OBJECT
Q_PROPERTY(Status status READ status NOTIFY statusChanged)
Q_PROPERTY(QOAuthTokenPair clientId READ clientId WRITE setClientId NOTIFY clientIdChanged)
Q_PROPERTY(QOAuthTokenPair token READ token WRITE setToken NOTIFY tokenChanged)
Q_PROPERTY(QVariantMap extraTokens READ extraTokens NOTIFY extraTokensChanged)
Q_PROPERTY(QNetworkAccessManager::Operation operation READ operation WRITE setOperation
NOTIFY operationChanged)
public:
// explicit QAbstractOAuth(QObject *parent = nullptr);
struct OAUTH_EXPORT Credential {
QString key;
Credential();
Credential(const QString &credentialKey);
};
virtual ~QAbstractOAuth();
enum class Status {
NotAuthenticated,
TokenReceived,
Authenticated
TemporaryTokenReceived,
Granted
};
Q_ENUM(Status)
enum class SignatureMethod {
PlainText,
Hmac_Sha1
enum class Stage {
RequestingTemporaryCredentials,
RequestingAuthorization,
RequestingAccessToken
};
Q_ENUM(SignatureMethod)
typedef std::function<void(Stage, QVariantMap*)> ModifyParametersFunction;
enum class Error {
NoError,
NetworkError,
ServerError,
OAuthTokenNotFoundError,
OAuthTokenSecretNotFoundError,
ServerError
OAuthCallbackNotVerified
};
Status status() const;
QUrl requestTokenUrl() const;
void setRequestTokenUrl(const QUrl &url);
QUrl authorizationGrantUrl() const;
void setAuthorizationGrantUrl(const QUrl &url);
QOAuthTokenPair clientId() const;
void setClientId(const QOAuthTokenPair &value);
QOAuthTokenPair token() const;
void setToken(const QOAuthTokenPair &value);
void setToken(const QString &token, const QString &secret);
QUrl authorizeUrl() const;
void setAuthorizeUrl(const QUrl &url);
QVariantMap extraTokens() const;
QNetworkAccessManager::Operation operation() const;
void setOperation(QNetworkAccessManager::Operation operation);
QAbstractOAuthReplyHandler *replyHandler() const;
void setReplyHandler(QAbstractOAuthReplyHandler *handler);
......@@ -129,24 +122,24 @@ public:
virtual QNetworkReply *post(const QNetworkRequest &req,
const QVariantMap &parameters = QVariantMap()) = 0;
ModifyParametersFunction modifyParametersFunction() const;
void setModifyParametersFunction(const ModifyParametersFunction &modifyParametersFunction);
public Q_SLOTS:
virtual void grant() = 0;
Q_SIGNALS:
void openBrowser(const QUrl &url);
void closeBrowser();
void requestFailed(const Error error);
void statusChanged(Status status);
void requestTokenUrlChanged();
void authorizationGrantUrlChanged();
void clientIdChanged(const QOAuthTokenPair &clientId);
void tokenChanged(const QOAuthTokenPair &token);
void accessTokenChanged(const QOAuthTokenPair &token);
void requestTokenUrlChanged(const QUrl &url);
void authorizationGrantUrlChanged(const QUrl &url);
void authorizeUrlChanged(const QUrl &url);
void extraTokensChanged(const QVariantMap &tokens);
void operationChanged();
void authenticationRequested(const QUrl &url);
void granted();
......@@ -155,27 +148,6 @@ protected:
void setStatus(Status status);
// static QByteArray parameterString(const QVariantMap &parameters);
// static QByteArray nonce();
// static QByteArray signatureBase(const QVariantMap &parameters,
// const QUrl &url,
// QNetworkAccessManager::Operation op);
// static QByteArray encodeHeaders(const QVariantMap &headers);
// static QByteArray sign(const QVariantMap &parameters,
// const QUrl &url,
// QNetworkAccessManager::Operation op,
// const QString &consumerSecret,
// const QString &tokenSecret);
// static QByteArray generateAuthorizationHeader(const QVariantMap &oauthParams);
// QByteArray generateSignature(const QVariantMap &parameters, const QUrl &req,
// QNetworkAccessManager::Operation operation);
QString callback() const;
private:
......
......@@ -50,21 +50,57 @@
#include <qnetworkaccessmanager.h>
#include <qmessageauthenticationcode.h>
#include <random>
QT_BEGIN_NAMESPACE
typedef QAbstractOAuth2Private::OAuth2KeyString Key;
const QString Key::accessToken = QStringLiteral("access_token");
const QString Key::clientId = QStringLiteral("client_id");
const QString Key::code = QStringLiteral("code");
const QString Key::error = QStringLiteral("error");
const QString Key::errorDescription = QStringLiteral("error_description");
const QString Key::errorUri = QStringLiteral("error_uri");
const QString Key::expiresIn = QStringLiteral("expires_in");
const QString Key::grantType = QStringLiteral("grant_type");
const QString Key::redirectUri = QStringLiteral("redirect_uri");
const QString Key::refreshToken = QStringLiteral("refresh_token");
const QString Key::responseType = QStringLiteral("response_type");
const QString Key::scope = QStringLiteral("scope");
const QString Key::state = QStringLiteral("state");
const QString Key::tokenType = QStringLiteral("token_type");
QAbstractOAuth2Private::QAbstractOAuth2Private(QNetworkAccessManager *manager)
: QAbstractOAuthPrivate(manager)
{}
{
qRegisterMetaType<QAbstractOAuth2::Credential>("QAbstractOAuth2::Credential");
}
QAbstractOAuth2Private::~QAbstractOAuth2Private()
{}
QString QAbstractOAuth2Private::generateRandomState()
{
const QString characters = QStringLiteral("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789");
std::mt19937 randomEngine;
std::uniform_int_distribution<int> distribution(0, characters.size() - 1);
QString string;
const int length = 8;
for(int i=0; i < length; ++i) {
const QChar character = characters.at(distribution(randomEngine));
string.append(character);
}
return string;
}
QAbstractOAuth2::QAbstractOAuth2(QNetworkAccessManager *manager, QObject *parent)
: QAbstractOAuth(*new QAbstractOAuth2Private(manager), parent)
{}
QAbstractOAuth2::QAbstractOAuth2(QAbstractOAuth2Private &dd, QObject *parent)
: QAbstractOAuth(dd, parent)
{}
......@@ -85,8 +121,8 @@ QNetworkReply *QAbstractOAuth2::get(const QNetworkRequest &req, const QVariantMa
QNetworkRequest request(req);
request.setUrl(url);
QByteArray bearer("bearer ");
bearer.append(d->token.first.toLocal8Bit());
request.setRawHeader("User-Agent", "qoauth/0.1");
bearer.append(d->token.key.toLocal8Bit());
request.setHeader(QNetworkRequest::UserAgentHeader, d->userAgent);
request.setRawHeader("Authorization", bearer);
return d->networkAccessManager->get(request);
......@@ -107,8 +143,8 @@ QNetworkReply *QAbstractOAuth2::post(const QNetworkRequest &req, const QVariantM
QNetworkRequest request(req);
request.setUrl(url);
QByteArray bearer("bearer ");
bearer.append(d->token.first.toLocal8Bit());
request.setRawHeader("User-Agent", "qoauth/0.1");
bearer.append(d->token.key.toLocal8Bit());
request.setHeader(QNetworkRequest::UserAgentHeader, d->userAgent);
request.setRawHeader("Authorization", bearer);
return d->networkAccessManager->post(request, QByteArray());
......@@ -129,18 +165,48 @@ void QAbstractOAuth2::setScope(const QString &scope)
}
}
QString QAbstractOAuth2::apiKey() const
QString QAbstractOAuth2::userAgent() const
{
Q_D(const QAbstractOAuth2);
return d->apiKey;
return d->userAgent;
}
void QAbstractOAuth2::setUserAgent(const QString &userAgent)
{
Q_D(QAbstractOAuth2);
if (d->userAgent != userAgent) {
d->userAgent = userAgent;
Q_EMIT userAgentChanged(userAgent);
}
}
QAbstractOAuth2::Credential QAbstractOAuth2::consumerToken() const
{
Q_D(const QAbstractOAuth2);
return d->consumer;
}
QAbstractOAuth2::Credential QAbstractOAuth2::token() const
{
Q_D(const QAbstractOAuth2);
return d->token;
}
void QAbstractOAuth2::setConsumerToken(const QAbstractOAuth2::Credential consumerToken)
{
Q_D(QAbstractOAuth2);
if (d->consumer.key != consumerToken.key) {
d->consumer.key = consumerToken.key;
Q_EMIT consumerTokenChanged(consumerToken);
}
}
void QAbstractOAuth2::setApiKey(const QString &apiKey)
void QAbstractOAuth2::setToken(const QAbstractOAuth2::Credential &token)
{
Q_D(QAbstractOAuth2);
if (d->apiKey != apiKey) {
d->apiKey = apiKey;
Q_EMIT apiKeyChanged(apiKey);
if (d->token.key != token.key) {
d->token = token;
Q_EMIT tokenChanged(token);
}
}
......
......@@ -47,13 +47,10 @@
QT_BEGIN_NAMESPACE
class QAbstractOAuth2Private;
class Q_NETWORK_EXPORT QAbstractOAuth2 : public QAbstractOAuth
class OAUTH_EXPORT QAbstractOAuth2 : public QAbstractOAuth
{
Q_OBJECT
Q_PROPERTY(QString scope READ scope WRITE setScope NOTIFY scopeChanged)
Q_PROPERTY(QString apiKey READ apiKey WRITE setApiKey NOTIFY apiKeyChanged)
public:
explicit QAbstractOAuth2(QNetworkAccessManager *manager, QObject *parent = nullptr);
virtual ~QAbstractOAuth2();
......@@ -66,15 +63,25 @@ public:
QString scope() const;
void setScope(const QString &scope);
QString apiKey() const;
void setApiKey(const QString &apiKey);