This commit is contained in:
Kyle Fowler 2012-03-22 20:40:35 -07:00
parent 21ce26a3d8
commit 98426ae24a
21 changed files with 2471 additions and 1 deletions

View file

@ -1,4 +1,5 @@
#About the oauth library for BlackBerry 10 About the oauth library for BlackBerry 10
==========================================
This is a OAuth library built for the Cascades development framework for BlackBerry 10. It is a fork and BlackBerry specific implementation of the KQOauth library that can be found here http://www.gitorious.org/kqoauth under the LGPL license. This is a OAuth library built for the Cascades development framework for BlackBerry 10. It is a fork and BlackBerry specific implementation of the KQOauth library that can be found here http://www.gitorious.org/kqoauth under the LGPL license.
This library supports both OAuth1 and OAuth2 authorization flow and authorized requests. This library supports both OAuth1 and OAuth2 authorization flow and authorized requests.

56
oauth/kqoauth2request.cpp Normal file
View file

@ -0,0 +1,56 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtDebug>
#include "kqoauth2request_p.h"
#include "kqoauth2request.h"
/**
* Private d_ptr implementations.
*/
KQOAuth2Request_Private::KQOAuth2Request_Private()
{
}
KQOAuth2Request_Private::~KQOAuth2Request_Private()
{
}
/**
* Public implementations.
*/
KQOAuth2Request::KQOAuth2Request(QObject *parent) :
KQOAuthRequest(parent),
d_ptr(new KQOAuth2Request_Private)
{
}
bool KQOAuth2Request::isValid() const {
// Access token must always be retrieved using the POST HTTP method.
// And then check the validity of the XAuth request.
// Provided by the base class as a protected method for us.
return validateOauth2Request();
}
void KQOAuth2Request::initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint) {
KQOAuthRequest::initRequest(type,requestEndpoint);
setRequestOAuthMethod(KQOAuthRequest::OAUTH2);
}

45
oauth/kqoauth2request.h Normal file
View file

@ -0,0 +1,45 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTH2REQUEST_H
#define KQOAUTH2REQUEST_H
#include "kqoauthrequest.h"
#include "kqoauthrequest_1.h"
class KQOAuth2Request_Private;
class KQOAUTH_EXPORT KQOAuth2Request : public KQOAuthRequest
{
Q_OBJECT
public:
KQOAuth2Request(QObject *parent = 0);
/**
* These methods can be overridden in child classes which are different types of
* OAuth requests.
*/
// Validate the request of this type.
bool isValid() const;
void initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint);
private:
KQOAuth2Request_Private * const d_ptr;
};
#endif // KQOAUTHREQUEST_XAUTH_H

14
oauth/kqoauth2request_p.h Normal file
View file

@ -0,0 +1,14 @@
#ifndef KQOAUTH2REQUEST_P_H
#define KQOAUTH2REQUEST_P_H
#include "kqoauthglobals.h"
class KQOAuthRequest;
class KQOAUTH_EXPORT KQOAuth2Request_Private
{
public:
KQOAuth2Request_Private();
~KQOAuth2Request_Private();
};
#endif // KQOAUTHREQUEST_XAUTH_P_H

View file

@ -0,0 +1,110 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QTcpSocket>
#include <QStringList>
#include <QUrl>
#include "kqoauthauthreplyserver.h"
#include "kqoauthauthreplyserver_p.h"
KQOAuthAuthReplyServerPrivate::KQOAuthAuthReplyServerPrivate(KQOAuthAuthReplyServer *parent):
q_ptr(parent)
{
}
KQOAuthAuthReplyServerPrivate::~KQOAuthAuthReplyServerPrivate()
{
}
void KQOAuthAuthReplyServerPrivate::onIncomingConnection() {
Q_Q(KQOAuthAuthReplyServer);
socket = q->nextPendingConnection();
connect(socket, SIGNAL(readyRead()),
this, SLOT(onBytesReady()), Qt::UniqueConnection);
}
void KQOAuthAuthReplyServerPrivate::onBytesReady() {
Q_Q(KQOAuthAuthReplyServer);
QByteArray reply;
QByteArray content;
content.append("<HTML><h1>Account authorized, go ahead back to the tumblr app and start your experience!</h1></HTML>");
reply.append("HTTP/1.0 200 OK \r\n");
reply.append("Content-Type: text/html; charset=\"utf-8\"\r\n");
reply.append(QString("Content-Length: %1\r\n").arg(content.size()));
reply.append("\r\n");
reply.append(content);
socket->write(reply);
QByteArray data = socket->readAll();
QMultiMap<QString, QString> queryParams = parseQueryParams(&data);
socket->disconnectFromHost();
q->close();
emit q->verificationReceived(queryParams);
}
QMultiMap<QString, QString> KQOAuthAuthReplyServerPrivate::parseQueryParams(QByteArray *data) {
QString splitGetLine = QString(*data).split("\r\n").first(); // Retrieve the first line with query params.
splitGetLine.remove("GET "); // Clean the line from GET
splitGetLine.remove("HTTP/1.1"); // From HTTP
splitGetLine.remove("\r\n"); // And from rest.
splitGetLine.prepend("http://localhost"); // Now, make it a URL
QUrl getTokenUrl(splitGetLine);
QList< QPair<QString, QString> > tokens = getTokenUrl.queryItems(); // Ask QUrl to do our work.
QMultiMap<QString, QString> queryParams;
QPair<QString, QString> tokenPair;
foreach (tokenPair, tokens) {
queryParams.insert(tokenPair.first.trimmed(), tokenPair.second.trimmed());
}
return queryParams;
}
KQOAuthAuthReplyServer::KQOAuthAuthReplyServer(QObject *parent) :
QTcpServer(parent),
d_ptr( new KQOAuthAuthReplyServerPrivate(this) )
{
Q_D(KQOAuthAuthReplyServer);
connect(this, SIGNAL(newConnection()),
d, SLOT(onIncomingConnection()));
}
KQOAuthAuthReplyServer::~KQOAuthAuthReplyServer()
{
delete d_ptr;
}
void KQOAuthAuthReplyServer::setSuccessHtmlFile(QString filePath) {
Q_D(KQOAuthAuthReplyServer);
d->localFile = filePath;
}

View file

@ -0,0 +1,48 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHAUTHREPLYSERVER_H
#define KQOAUTHAUTHREPLYSERVER_H
#include <QTcpServer>
#include "kqoauthglobals.h"
class KQOAuthAuthReplyServerPrivate;
class KQOAUTH_EXPORT KQOAuthAuthReplyServer : public QTcpServer
{
Q_OBJECT
public:
explicit KQOAuthAuthReplyServer(QObject *parent);
~KQOAuthAuthReplyServer();
void setSuccessHtmlFile(QString filePath);
Q_SIGNALS:
void verificationReceived(QMultiMap<QString, QString>);
private:
KQOAuthAuthReplyServerPrivate * const d_ptr;
Q_DECLARE_PRIVATE(KQOAuthAuthReplyServer);
Q_DISABLE_COPY(KQOAuthAuthReplyServer);
};
#endif // KQOAUTHAUTHREPLYSERVER_H

View file

@ -0,0 +1,47 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
// Note this class shouldn't be copied or used and the implementation might change later.
#ifndef KQOAUTHAUTHREPLYSERVER_P_H
#define KQOAUTHAUTHREPLYSERVER_P_H
#include "kqoauthauthreplyserver.h"
#include <QMultiMap>
#include <QString>
class KQOAUTH_EXPORT KQOAuthAuthReplyServerPrivate: public QObject
{
Q_OBJECT
public:
KQOAuthAuthReplyServerPrivate( KQOAuthAuthReplyServer * parent );
~KQOAuthAuthReplyServerPrivate();
QMultiMap<QString, QString> parseQueryParams(QByteArray *sdata);
public Q_SLOTS:
void onIncomingConnection();
void onBytesReady();
public:
KQOAuthAuthReplyServer * q_ptr;
Q_DECLARE_PUBLIC(KQOAuthAuthReplyServer);
QTcpSocket *socket;
QString localFile;
};
#endif // KQOAUTHAUTHREPLYSERVER_P_H

48
oauth/kqoauthglobals.h Normal file
View file

@ -0,0 +1,48 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHGLOBALS_H
#define KQOAUTHGLOBALS_H
#include <QtCore/qglobal.h>
#if defined(KQOAUTH)
# define KQOAUTH_EXPORT Q_DECL_EXPORT
#else
# define KQOAUTH_EXPORT Q_DECL_IMPORT
#endif
//////////// Static constant definitions ///////////
const QString OAUTH_KEY_CONSUMER("oauth_consumer");
const QString OAUTH_KEY_CONSUMER_KEY("oauth_consumer_key");
const QString OAUTH_KEY_TOKEN("oauth_token");
const QString OAUTH_KEY_TOKEN_SECRET("oauth_token_secret");
const QString OAUTH_KEY_SIGNATURE_METHOD("oauth_signature_method");
const QString OAUTH_KEY_TIMESTAMP("oauth_timestamp");
const QString OAUTH_KEY_NONCE("oauth_nonce");
const QString OAUTH_KEY_SIGNATURE("oauth_signature");
const QString OAUTH_KEY_CALLBACK("oauth_callback");
const QString OAUTH_KEY_VERIFIER("oauth_verifier");
const QString OAUTH_KEY_VERSION("oauth_version");
const QString OAUTH2_KEY_CLIENT_ID("client_id");
const QString OAUTH2_KEY_CLIENT_SECRET("client_secret");
const QString OAUTH2_KEY_REDIRECT_URI("redirect_uri");
const QString OAUTH2_KEY_RESPONSE_TYPE("response_type");
#endif // KQOAUTHGLOBALS_H

677
oauth/kqoauthmanager.cpp Normal file
View file

@ -0,0 +1,677 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtCore>
#include "kqoauthmanager.h"
#include "kqoauthmanager_p.h"
#include "bps/navigator.h"
////////////// Private d_ptr implementation ////////////////
KQOAuthManagerPrivate::KQOAuthManagerPrivate(KQOAuthManager *parent) :
error(KQOAuthManager::NoError) ,
r(0) ,
opaqueRequest(new KQOAuthRequest) ,
q_ptr(parent) ,
callbackServer(new KQOAuthAuthReplyServer(parent)) ,
isVerified(false) ,
isAuthorized(false) ,
autoAuth(false),
networkManager(new QNetworkAccessManager),
managerUserSet(false)
{
}
KQOAuthManagerPrivate::~KQOAuthManagerPrivate() {
delete opaqueRequest;
opaqueRequest = 0;
if (!managerUserSet) {
delete networkManager;
networkManager = 0;
}
}
QList< QPair<QString, QString> > KQOAuthManagerPrivate::createQueryParams(const KQOAuthParameters &requestParams) {
QList<QString> requestKeys = requestParams.keys();
QList<QString> requestValues = requestParams.values();
QList< QPair<QString, QString> > result;
for(int i=0; i<requestKeys.size(); i++) {
result.append( qMakePair(requestKeys.at(i),
requestValues.at(i))
);
}
return result;
}
QMultiMap<QString, QString> KQOAuthManagerPrivate::createTokensFromResponse(QByteArray reply) {
QMultiMap<QString, QString> result;
QString replyString(reply);
QStringList parameterPairs = replyString.split('&', QString::SkipEmptyParts);
foreach (const QString &parameterPair, parameterPairs) {
QStringList parameter = parameterPair.split('=');
result.insert(parameter.value(0), parameter.value(1));
}
return result;
}
bool KQOAuthManagerPrivate::setSuccessfulRequestToken(const QMultiMap<QString, QString> &request) {
if (currentRequestType == KQOAuthRequest::TemporaryCredentials) {
hasTemporaryToken = (!QString(request.value("oauth_token")).isEmpty() && !QString(request.value("oauth_token_secret")).isEmpty());
} else {
return false;
}
if (hasTemporaryToken) {
requestToken = QUrl::fromPercentEncoding( QString(request.value("oauth_token")).toLocal8Bit() );
requestTokenSecret = QUrl::fromPercentEncoding( QString(request.value("oauth_token_secret")).toLocal8Bit() );
}
return hasTemporaryToken;
}
bool KQOAuthManagerPrivate::setSuccessfulAuthorized(const QMultiMap<QString, QString> &request ) {
if (currentRequestType == KQOAuthRequest::AccessToken) {
isAuthorized = (!QString(request.value("oauth_token")).isEmpty() && !QString(request.value("oauth_token_secret")).isEmpty());
} else {
return false;
}
if (isAuthorized) {
requestToken = QUrl::fromPercentEncoding( QString(request.value("oauth_token")).toLocal8Bit() );
requestTokenSecret = QUrl::fromPercentEncoding( QString(request.value("oauth_token_secret")).toLocal8Bit() );
}
return isAuthorized;
}
void KQOAuthManagerPrivate::emitTokens() {
Q_Q(KQOAuthManager);
if (this->requestToken.isEmpty() || this->requestTokenSecret.isEmpty()) {
error = KQOAuthManager::RequestUnauthorized;
}
if (currentRequestType == KQOAuthRequest::TemporaryCredentials) {
// Signal that we are ready to use the protected resources.
emit q->temporaryTokenReceived(this->requestToken, this->requestTokenSecret);
}
if (currentRequestType == KQOAuthRequest::AccessToken) {
// Signal that we are ready to use the protected resources.
emit q->accessTokenReceived(this->requestToken, this->requestTokenSecret);
}
emit q->receivedToken(this->requestToken, this->requestTokenSecret);
}
bool KQOAuthManagerPrivate::setupCallbackServer() {
return callbackServer->listen();
}
/////////////// Public implementation ////////////////
KQOAuthManager::KQOAuthManager(QObject *parent) :
QObject(parent) ,
d_ptr(new KQOAuthManagerPrivate(this))
{
}
KQOAuthManager::~KQOAuthManager()
{
delete d_ptr;
}
void KQOAuthManager::executeRequest(KQOAuthRequest *request) {
Q_D(KQOAuthManager);
d->r = request;
if (request == 0) {
qWarning() << "Request is NULL. Cannot proceed.";
d->error = KQOAuthManager::RequestError;
return;
}
if (!request->requestEndpoint().isValid()) {
qWarning() << "Request endpoint URL is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestEndpointError;
return;
}
if (!request->isValid()) {
qWarning() << "Request is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestValidationError;
return;
}
d->currentRequestType = request->requestType();
QNetworkRequest networkRequest;
networkRequest.setUrl( request->requestEndpoint() );
if (d->autoAuth && d->currentRequestType == KQOAuthRequest::TemporaryCredentials) {
d->setupCallbackServer();
connect(d->callbackServer, SIGNAL(verificationReceived(QMultiMap<QString, QString>)),
this, SLOT( onVerificationReceived(QMultiMap<QString, QString>)));
QString serverString = "http://localhost:";
serverString.append(QString::number(d->callbackServer->serverPort()));
request->setCallbackUrl(QUrl(serverString));
qDebug() << serverString;
}
// And now fill the request with "Authorization" header data.
QList<QByteArray> requestHeaders = request->requestParameters();
QByteArray authHeader;
bool first = true;
foreach (const QByteArray header, requestHeaders) {
if (!first) {
authHeader.append(", ");
} else {
authHeader.append("OAuth ");
first = false;
}
authHeader.append(header);
}
networkRequest.setRawHeader("Authorization", authHeader);
connect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onRequestReplyReceived(QNetworkReply *)), Qt::UniqueConnection);
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply *)));
if (request->httpMethod() == KQOAuthRequest::GET) {
// Get the requested additional params as a list of pairs we can give QUrl
QList< QPair<QString, QString> > urlParams = d->createQueryParams(request->additionalParameters());
// Take the original URL and append the query params to it.
QUrl urlWithParams = networkRequest.url();
urlWithParams.setQueryItems(urlParams);
networkRequest.setUrl(urlWithParams);
// Submit the request including the params.
QNetworkReply *reply = d->networkManager->get(networkRequest);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
} else if (request->httpMethod() == KQOAuthRequest::POST) {
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, request->contentType());
qDebug() << networkRequest.rawHeaderList();
qDebug() << networkRequest.rawHeader("Authorization");
qDebug() << networkRequest.rawHeader("Content-Type");
QNetworkReply *reply;
if (request->contentType() == "application/x-www-form-urlencoded") {
reply = d->networkManager->post(networkRequest, request->requestBody());
} else {
reply = d->networkManager->post(networkRequest, request->rawData());
}
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
}
d->r->requestTimerStart();
}
void KQOAuthManager::executeAuthorizedRequest(KQOAuthRequest *request, int id) {
Q_D(KQOAuthManager);
d->r = request;
if (request == 0) {
qWarning() << "Request is NULL. Cannot proceed.";
d->error = KQOAuthManager::RequestError;
return;
}
if (!request->requestEndpoint().isValid()) {
qWarning() << "Request endpoint URL is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestEndpointError;
return;
}
if (!request->isValid()) {
qWarning() << "Request is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestValidationError;
return;
}
d->currentRequestType = request->requestType();
QNetworkRequest networkRequest;
networkRequest.setUrl( request->requestEndpoint() );
if ( d->currentRequestType != KQOAuthRequest::AuthorizedRequest){
qWarning() << "Not Authorized Request. Cannot proceed";
d->error = KQOAuthManager::RequestError;
return;
}
if(request->oauthMethod() != KQOAuthRequest::OAUTH2) {
// And now fill the request with "Authorization" header data.
QList<QByteArray> requestHeaders = request->requestParameters();
QByteArray authHeader;
bool first = true;
foreach (const QByteArray header, requestHeaders) {
if (!first) {
authHeader.append(", ");
} else {
authHeader.append("OAuth ");
first = false;
}
authHeader.append(header);
}
networkRequest.setRawHeader("Authorization", authHeader);
}
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onRequestReplyReceived(QNetworkReply *)));
connect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply*)), Qt::UniqueConnection);
if (request->httpMethod() == KQOAuthRequest::GET) {
// Get the requested additional params as a list of pairs we can give QUrl
QList< QPair<QString, QString> > urlParams = d->createQueryParams(request->additionalParameters());
// Take the original URL and append the query params to it.
QUrl urlWithParams = networkRequest.url();
urlWithParams.setQueryItems(urlParams);
networkRequest.setUrl(urlWithParams);
// Submit the request including the params.
QNetworkReply *reply = d->networkManager->get(networkRequest);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
} else if (request->httpMethod() == KQOAuthRequest::POST) {
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, request->contentType());
/*
qDebug() << networkRequest.rawHeaderList();
qDebug() << networkRequest.rawHeader("Authorization");
qDebug() << networkRequest.rawHeader("Content-Type");
*/
QNetworkReply *reply;
if (request->contentType() == "application/x-www-form-urlencoded") {
reply = d->networkManager->post(networkRequest, request->requestBody());
} else {
reply = d->networkManager->post(networkRequest, request->rawData());
}
d->requestIds.insert(reply, id);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(slotError(QNetworkReply::NetworkError)));
}
d->r->requestTimerStart();
}
void KQOAuthManager::setHandleUserAuthorization(bool set) {
Q_D(KQOAuthManager);
d->autoAuth = set;
}
bool KQOAuthManager::hasTemporaryToken() {
Q_D(KQOAuthManager);
return d->hasTemporaryToken;
}
bool KQOAuthManager::isVerified() {
Q_D(KQOAuthManager);
return d->isVerified;
}
bool KQOAuthManager::isAuthorized() {
Q_D(KQOAuthManager);
return d->isAuthorized;
}
KQOAuthManager::KQOAuthError KQOAuthManager::lastError() {
Q_D(KQOAuthManager);
return d->error;
}
void KQOAuthManager::setNetworkManager(QNetworkAccessManager *manager) {
Q_D(KQOAuthManager);
if (manager == 0) {
d->error = KQOAuthManager::ManagerError;
return;
}
if (!d->managerUserSet) {
delete d->networkManager;
}
d->managerUserSet = true;
d->networkManager = manager;
}
QNetworkAccessManager * KQOAuthManager::networkManager() const {
Q_D(const KQOAuthManager);
if (d->managerUserSet) {
return d->networkManager;
} else {
return NULL;
}
}
void KQOAuthManager::setSuccessHtmlFile(QString file) {
Q_D(KQOAuthManager);
d->successHtmlFile = file;
d->callbackServer->setSuccessHtmlFile(file);
}
//////////// Public convenience API /////////////
void KQOAuthManager::getOauth2UserAuthorization(QUrl authorizationEndpoint, QString consumerKey) {
Q_D(KQOAuthManager);
d->setupCallbackServer();
connect(d->callbackServer, SIGNAL(verificationReceived(QMultiMap<QString, QString>)),
this, SLOT( onVerificationReceived(QMultiMap<QString, QString>)));
QString serverString = "http://localhost:";
serverString.append(QString::number(d->callbackServer->serverPort()));
QUrl openWebPageUrl(authorizationEndpoint.toString(), QUrl::StrictMode);
openWebPageUrl.addQueryItem(OAUTH2_KEY_CLIENT_ID, consumerKey);
openWebPageUrl.addQueryItem(OAUTH2_KEY_RESPONSE_TYPE, "token");
openWebPageUrl.addQueryItem(OAUTH2_KEY_REDIRECT_URI, serverString);
qDebug() << openWebPageUrl.toString();
navigator_invoke(openWebPageUrl.toString().toStdString().c_str(),0);
}
void KQOAuthManager::getUserAuthorization(QUrl authorizationEndpoint) {
Q_D(KQOAuthManager);
if (!d->hasTemporaryToken) {
qWarning() << "No temporary tokens retreieved. Cannot get user authorization.";
d->error = KQOAuthManager::RequestUnauthorized;
return;
}
if (!authorizationEndpoint.isValid()) {
qWarning() << "Authorization endpoint not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestEndpointError;
return;
}
d->error = KQOAuthManager::NoError;
QPair<QString, QString> tokenParam = qMakePair(QString("oauth_token"), QString(d->requestToken));
QUrl openWebPageUrl(authorizationEndpoint.toString(), QUrl::StrictMode);
openWebPageUrl.addQueryItem(tokenParam.first, tokenParam.second);
// Open the user's default browser to the resource authorization page provided
// by the service.
qDebug() << openWebPageUrl.toString();
navigator_invoke(openWebPageUrl.toString().toStdString().c_str(),0);
}
void KQOAuthManager::getUserAccessTokens(QUrl accessTokenEndpoint) {
Q_D(KQOAuthManager);
if (!d->isVerified) {
qWarning() << "Not verified. Cannot get access tokens.";
d->error = KQOAuthManager::RequestUnauthorized;
return;
}
if (!accessTokenEndpoint.isValid()) {
qWarning() << "Endpoint for access token exchange is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestEndpointError;
return;
}
d->error = KQOAuthManager::NoError;
d->opaqueRequest->clearRequest();
d->opaqueRequest->initRequest(KQOAuthRequest::AccessToken, accessTokenEndpoint);
d->opaqueRequest->setToken(d->requestToken);
d->opaqueRequest->setTokenSecret(d->requestTokenSecret);
d->opaqueRequest->setVerifier(d->requestVerifier);
d->opaqueRequest->setConsumerKey(d->consumerKey);
d->opaqueRequest->setConsumerSecretKey(d->consumerKeySecret);
executeRequest(d->opaqueRequest);
}
void KQOAuthManager::sendAuthorizedRequest(QUrl requestEndpoint, const KQOAuthParameters &requestParameters) {
Q_D(KQOAuthManager);
if (!d->isAuthorized) {
qWarning() << "No access tokens retrieved. Cannot send authorized requests.";
d->error = KQOAuthManager::RequestUnauthorized;
return;
}
if (!requestEndpoint.isValid()) {
qWarning() << "Endpoint for authorized request is not valid. Cannot proceed.";
d->error = KQOAuthManager::RequestEndpointError;
return;
}
d->error = KQOAuthManager::NoError;
d->opaqueRequest->clearRequest();
d->opaqueRequest->initRequest(KQOAuthRequest::AuthorizedRequest, requestEndpoint);
d->opaqueRequest->setAdditionalParameters(requestParameters);
d->opaqueRequest->setToken(d->requestToken);
d->opaqueRequest->setTokenSecret(d->requestTokenSecret);
d->opaqueRequest->setConsumerKey(d->consumerKey);
d->opaqueRequest->setConsumerSecretKey(d->consumerKeySecret);
executeRequest(d->opaqueRequest);
}
/////////////// Private slots //////////////////
void KQOAuthManager::onRequestReplyReceived( QNetworkReply *reply ) {
Q_D(KQOAuthManager);
QNetworkReply::NetworkError networkError = reply->error();
switch (networkError) {
case QNetworkReply::NoError:
d->error = KQOAuthManager::NoError;
break;
case QNetworkReply::ContentAccessDenied:
case QNetworkReply::AuthenticationRequiredError:
d->error = KQOAuthManager::RequestUnauthorized;
break;
default:
d->error = KQOAuthManager::NetworkError;
break;
}
// Let's disconnect this slot first
/*
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onRequestReplyReceived(QNetworkReply *)));
*/
// Read the content of the reply from the network.
QByteArray networkReply = reply->readAll();
// Stop any timer we have set on the request.
d->r->requestTimerStop();
// Just don't do anything if we didn't get anything useful.
if(networkReply.isEmpty()) {
reply->deleteLater();
return;
}
QMultiMap<QString, QString> responseTokens;
// We need to emit the signal even if we got an error.
if (d->error != KQOAuthManager::NoError) {
reply->deleteLater();
emit requestReady(networkReply);
d->emitTokens();
return;
}
responseTokens = d->createTokensFromResponse(networkReply);
d->opaqueRequest->clearRequest();
d->opaqueRequest->setHttpMethod(KQOAuthRequest::POST); // XXX FIXME: Convenient API does not support GET
if (!d->isAuthorized || !d->isVerified) {
if (d->setSuccessfulRequestToken(responseTokens)) {
qDebug() << "Successfully got request tokens.";
d->consumerKey = d->r->consumerKeyForManager();
d->consumerKeySecret = d->r->consumerKeySecretForManager();
d->opaqueRequest->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
d->opaqueRequest->setCallbackUrl(d->r->callbackUrlForManager());
d->emitTokens();
} else if (d->setSuccessfulAuthorized(responseTokens)) {
qDebug() << "Successfully got access tokens.";
d->opaqueRequest->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
d->emitTokens();
} else if (d->currentRequestType == KQOAuthRequest::AuthorizedRequest) {
emit authorizedRequestDone();
}
}
emit requestReady(networkReply);
reply->deleteLater(); // We need to clean this up, after the event processing is done.
}
void KQOAuthManager::onAuthorizedRequestReplyReceived( QNetworkReply *reply ) {
Q_D(KQOAuthManager);
QNetworkReply::NetworkError networkError = reply->error();
switch (networkError) {
case QNetworkReply::NoError:
d->error = KQOAuthManager::NoError;
break;
case QNetworkReply::ContentAccessDenied:
case QNetworkReply::AuthenticationRequiredError:
d->error = KQOAuthManager::RequestUnauthorized;
break;
default:
d->error = KQOAuthManager::NetworkError;
break;
}
/*
disconnect(d->networkManager, SIGNAL(finished(QNetworkReply *)),
this, SLOT(onAuthorizedRequestReplyReceived(QNetworkReply *)));
*/
// Read the content of the reply from the network.
QByteArray networkReply = reply->readAll();
// Stop any timer we have set on the request.
d->r->requestTimerStop();
// Just don't do anything if we didn't get anything useful.
if(networkReply.isEmpty()) {
reply->deleteLater();
return;
}
// We need to emit the signal even if we got an error.
if (d->error != KQOAuthManager::NoError) {
qWarning() << "Network reply error";
return;
}
d->opaqueRequest->clearRequest();
d->opaqueRequest->setHttpMethod(KQOAuthRequest::POST); // XXX FIXME: Convenient API does not support GET
if (d->currentRequestType == KQOAuthRequest::AuthorizedRequest) {
emit authorizedRequestDone();
}
int id = d->requestIds.take(reply);
emit authorizedRequestReady(networkReply, id);
reply->deleteLater();
}
void KQOAuthManager::onVerificationReceived(QMultiMap<QString, QString> response) {
Q_D(KQOAuthManager);
QString token = response.value("oauth_token");
QString verifier = response.value("oauth_verifier");
if (verifier.isEmpty()) {
d->error = KQOAuthManager::RequestUnauthorized;
}
verifier = QUrl::fromPercentEncoding(verifier.toUtf8()); // We get the raw URL response here so we need to convert it back
// to plain string so we can percent encode it again later in requests.
if (d->error == KQOAuthManager::NoError) {
d->requestVerifier = verifier;
d->isVerified = true;
}
emit authorizationReceived(token, verifier);
}
void KQOAuthManager::slotError(QNetworkReply::NetworkError error) {
Q_UNUSED(error)
Q_D(KQOAuthManager);
d->error = KQOAuthManager::NetworkError;
QByteArray emptyResponse;
emit requestReady(emptyResponse);
emit authorizedRequestDone();
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
d->requestIds.remove(reply);
reply->deleteLater();
}

192
oauth/kqoauthmanager.h Normal file
View file

@ -0,0 +1,192 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHMANAGER_H
#define KQOAUTHMANAGER_H
#include <QObject>
#include <QMultiMap>
#include <QNetworkReply>
#include "kqoauthrequest.h"
class KQOAuthRequest;
class KQOAuthManagerThread;
class KQOAuthManagerPrivate;
class QNetworkAccessManager;
class QUrl;
class QByteArray;
class KQOAUTH_EXPORT KQOAuthManager : public QObject
{
Q_OBJECT
public:
enum KQOAuthError {
NoError, // No error
NetworkError, // Network error: timeout, cannot connect.
RequestEndpointError, // Request endpoint is not valid.
RequestValidationError, // Request is not valid: some parameter missing?
RequestUnauthorized, // Authorization error: trying to access a resource without tokens.
RequestError, // The given request to KQOAuthManager is invalid: NULL?,
ManagerError // Manager error, cannot use for sending requests.
};
explicit KQOAuthManager(QObject *parent = 0);
~KQOAuthManager();
KQOAuthError lastError();
/**
* The manager executes the given request. It takes the HTTP parameters from the
* request and uses QNetworkAccessManager to submit the HTTP request to the net.
* When the request is done it will emit signal requestReady(QByteArray networkReply).
* NOTE: At the moment there is no timeout for the request.
*/
void executeRequest(KQOAuthRequest *request);
void executeAuthorizedRequest(KQOAuthRequest *request, int id);
/**
* Indicates to the user that KQOAuthManager should handle user authorization by
* opening the user's default browser and parsing the reply from the service.
* By setting the parameter to true, KQOAuthManager will store intermediate results
* of the OAuth 1.0 process in its own opaque request. This information is used in
* the user authorization process and also when calling sendAuthorizedRequest().
* NOTE: You need to set this to true if you want to use getUserAccessTokens() or
* sendAuthorizedRequest().
*/
void setHandleUserAuthorization(bool set);
/**
* Returns true if the KQOAuthManager has retrieved the oauth_token value. Otherwise
* return false.
*/
bool hasTemporaryToken();
/**
* Returns true if the user has authorized us to use the protected resources. Otherwise
* returns false.
* NOTE: In order for KQOAuthManager to know if the user has authorized us to use the
* protected resources, KQOAuthManager must be in control of the user authorization
* process. Hence, this returns true if setHandleUserAuthorization() is set to true
* and the user is authorized with getUserAuthorization().
*/
bool isVerified();
/**
* Returns true if KQOAuthManager has the access token and hence can access the protected
* resources. Otherwise returns false.
* NOTE: In order for KQOAuthManager to know if we have access to protected resource
* KQOAuthManager must be in control of the user authorization process and requesting
* the acess token. Hence, this returns true if setHandleUserAuthorization() is set to true
* and the user is authorized with getUserAuthorization() and the access token must be retrieved
* with getUserAccessTokens.
*/
bool isAuthorized();
/**
* Sets the file path string that the local server will serve on a successful authentication. This will generally direct
* your user to go back to your application and continue using the app.
*/
void setSuccessHtmlFile(QString filePath);
/**
* This is a convenience API for authorizing the user.
* The call will open the user's default browser, setup a local HTTP server and parse the reply from the
* service after the user has authorized us to access protected resources. If the user authorizes
* us to access protected resources, the verifier token is stored in KQOAuthManager for further use.
* In order to use this method, you must set setHandleUserAuthorization() to true.
*/
void getUserAuthorization(QUrl authorizationEndpoint);
/**
* This is a convenience API for retrieving the access token in exchange for the temporary token and the
* verifier.
* This call will create a KQOAuthRequest and use the previously stored temporary token and verifier to
* exchange for the access token, which will be used to access the protected resources.
* Note that in order to use this method, KQOAuthManager must be in control of the user authorization process.
* Set setHandleUserAuthorization() to true and retrieve user authorization with void getUserAuthorization.
*/
void getUserAccessTokens(QUrl accessTokenEndpoint);
/**
* This is a method for bypassing all the oauth1 auth process and using the browser based oauth2 flow. This will
* launch the browser and set the callback url pointed to a localhost url. Make sure your oauth2 service supports redirect_uri param.
*/
void getOauth2UserAuthorization(QUrl authorizationEndpoint, QString consumerKey);
/**
* Sends a request to the protected resources. Parameters for the request are service specific and
* are given to the 'requestParameters' as parameters.
* Note that in order to use this method, KQOAuthManager must be in control of the user authorization process.
* Set setHandleUserAuthorization() to true and retrieve user authorization with void getUserAuthorization.
*/
void sendAuthorizedRequest(QUrl requestEndpoint, const KQOAuthParameters &requestParameters);
/**
* Sets a custom QNetworkAccessManager to handle network requests. This method can be useful if the
* application is using some proxy settings for example.
* The application is responsible for deleting this manager. KQOAuthManager will not delete any
* previously given manager.
* If the manager is NULL, the manager will not be set and the KQOAuthManager::Error.
* If no manager is given, KQOAuthManager will use the default one it will create by itself.
*/
void setNetworkManager(QNetworkAccessManager *manager);
/**
* Returns the given QNetworkAccessManager. Returns NULL if none is given.
*/
QNetworkAccessManager* networkManager() const;
Q_SIGNALS:
// This signal will be emitted after each request has got a reply.
// Parameter is the raw response from the service.
void requestReady(QByteArray networkReply);
void authorizedRequestReady(QByteArray networkReply, int id);
// This signal will be emited when we have an request tokens available
// (either temporary resource tokens, or authorization tokens).
void receivedToken(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
// This signal is emited when temporary tokens are returned from the service.
// Note that this signal is also emited in case temporary tokens are not available.
void temporaryTokenReceived(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
// This signal is emited when the user has authenticated the application to
// communicate with the protected resources. Next we need to exchange the
// temporary tokens for access tokens.
// Note that this signal is also emited if user denies access.
void authorizationReceived(QString oauth_token, QString oauth_verifier); // oauth_token, oauth_verifier
// This signal is emited when access tokens are received from the service. We are
// ready to start communicating with the protected resources.
void accessTokenReceived(QString oauth_token, QString oauth_token_secret); // oauth_token, oauth_token_secret
// This signal is emited when the authorized request is done.
// This ends the kQOAuth interactions.
void authorizedRequestDone();
private Q_SLOTS:
void onRequestReplyReceived( QNetworkReply *reply );
void onAuthorizedRequestReplyReceived( QNetworkReply *reply );
void onVerificationReceived(QMultiMap<QString, QString> response);
void slotError(QNetworkReply::NetworkError error);
private:
KQOAuthManagerPrivate *d_ptr;
Q_DECLARE_PRIVATE(KQOAuthManager);
Q_DISABLE_COPY(KQOAuthManager);
};
#endif // KQOAUTHMANAGER_H

74
oauth/kqoauthmanager_p.h Normal file
View file

@ -0,0 +1,74 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHMANAGER_P_H
#define KQOAUTHMANAGER_P_H
#include "kqoauthauthreplyserver.h"
#include "kqoauthrequest.h"
class KQOAUTH_EXPORT KQOAuthManagerPrivate {
public:
KQOAuthManagerPrivate(KQOAuthManager *parent);
~KQOAuthManagerPrivate();
QList< QPair<QString, QString> > createQueryParams(const KQOAuthParameters &requestParams);
QMultiMap<QString, QString> createTokensFromResponse(QByteArray reply);
bool setSuccessfulRequestToken(const QMultiMap<QString, QString> &request);
bool setSuccessfulAuthorized(const QMultiMap<QString, QString> &request);
void emitTokens();
bool setupCallbackServer();
KQOAuthManager::KQOAuthError error;
KQOAuthRequest *r; // This request is used to cache the user sent request.
KQOAuthRequest *opaqueRequest; // This request is used to creating opaque convenience requests for the user.
KQOAuthManager * const q_ptr;
/**
* The items below are needed in order to store the state of the manager and
* by that be able to do convenience operations for the user.
*/
KQOAuthRequest::RequestType currentRequestType;
// Variables we store here for opaque request handling.
// NOTE: The variables are labeled the same for both access token request
// and protected resource access.
QString requestToken;
QString requestTokenSecret;
QString consumerKey;
QString consumerKeySecret;
QString requestVerifier;
QString successHtmlFile;
KQOAuthAuthReplyServer *callbackServer;
bool hasTemporaryToken;
bool isVerified;
bool isAuthorized;
bool autoAuth;
QNetworkAccessManager *networkManager;
bool managerUserSet;
QMap<QNetworkReply*, int> requestIds;
Q_DECLARE_PUBLIC(KQOAuthManager);
};
#endif // KQOAUTHMANAGER_P_H

628
oauth/kqoauthrequest.cpp Normal file
View file

@ -0,0 +1,628 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QByteArray>
#include <QDateTime>
#include <QCryptographicHash>
#include <QPair>
#include <QStringList>
#include <QtDebug>
#include <QtAlgorithms>
#include "kqoauthrequest.h"
#include "kqoauthrequest_p.h"
#include "kqoauthutils.h"
#include "kqoauthglobals.h"
//////////// Private d_ptr implementation /////////
KQOAuthRequestPrivate::KQOAuthRequestPrivate() :
timeout(0)
{
}
KQOAuthRequestPrivate::~KQOAuthRequestPrivate()
{
}
// This method will not include the "oauthSignature" paramater, since it is calculated from these parameters.
void KQOAuthRequestPrivate::prepareRequest() {
// If parameter list is not empty, we don't want to insert these values by
// accident a second time. So giving up.
if( !requestParameters.isEmpty() ) {
return;
}
switch ( requestType ) {
case KQOAuthRequest::TemporaryCredentials:
requestParameters.append( qMakePair( OAUTH_KEY_CALLBACK, oauthCallbackUrl.toString()) ); // This is so ugly that it is almost beautiful.
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod) );
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
break;
case KQOAuthRequest::AccessToken:
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod ));
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
requestParameters.append( qMakePair( OAUTH_KEY_VERIFIER, oauthVerifier ));
requestParameters.append( qMakePair( OAUTH_KEY_TOKEN, oauthToken ));
break;
case KQOAuthRequest::AuthorizedRequest:
if(requestOAuthMethod == KQOAuthRequest::OAUTH1) {
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE_METHOD, oauthSignatureMethod ));
requestParameters.append( qMakePair( OAUTH_KEY_CONSUMER_KEY, oauthConsumerKey ));
requestParameters.append( qMakePair( OAUTH_KEY_VERSION, oauthVersion ));
requestParameters.append( qMakePair( OAUTH_KEY_TIMESTAMP, this->oauthTimestamp() ));
requestParameters.append( qMakePair( OAUTH_KEY_NONCE, this->oauthNonce() ));
requestParameters.append( qMakePair( OAUTH_KEY_TOKEN, oauthToken ));
}
break;
default:
break;
}
}
void KQOAuthRequestPrivate::signRequest() {
QString signature = this->oauthSignature();
requestParameters.append( qMakePair( OAUTH_KEY_SIGNATURE, signature) );
}
QString KQOAuthRequestPrivate::oauthSignature() {
/**
* http://oauth.net/core/1.0/#anchor16
* The HMAC-SHA1 signature method uses the HMAC-SHA1 signature algorithm as defined in [RFC2104] where the
* Signature Base String is the text and the key is the concatenated values (each first encoded per Parameter
* Encoding) of the Consumer Secret and Token Secret, separated by an & character (ASCII code 38) even if empty.
**/
QByteArray baseString = this->requestBaseString();
QString secret = QString(QUrl::toPercentEncoding(oauthConsumerSecretKey)) + "&" + QString(QUrl::toPercentEncoding(oauthTokenSecret));
QString signature = KQOAuthUtils::hmac_sha1(baseString, secret);
if (debugOutput) {
qDebug() << "========== KQOAuthRequest has the following signature:";
qDebug() << " * Signature : " << QUrl::toPercentEncoding(signature) << "\n";
}
return QString( QUrl::toPercentEncoding(signature) );
}
bool normalizedParameterSort(const QPair<QString, QString> &left, const QPair<QString, QString> &right) {
QString keyLeft = left.first;
QString valueLeft = left.second;
QString keyRight = right.first;
QString valueRight = right.second;
if(keyLeft == keyRight) {
return (valueLeft < valueRight);
} else {
return (keyLeft < keyRight);
}
}
QByteArray KQOAuthRequestPrivate::requestBaseString() {
QByteArray baseString;
// Every request has these as the commont parameters.
baseString.append( oauthHttpMethodString.toUtf8() + "&"); // HTTP method
baseString.append( QUrl::toPercentEncoding( oauthRequestEndpoint.toString(QUrl::RemoveQuery) ) + "&" ); // The path and query components
QList< QPair<QString, QString> > baseStringParameters;
baseStringParameters.append(requestParameters);
baseStringParameters.append(additionalParameters);
// Sort the request parameters. These parameters have been
// initialized earlier.
qSort(baseStringParameters.begin(),
baseStringParameters.end(),
normalizedParameterSort
);
// Last append the request parameters correctly encoded.
baseString.append( encodedParamaterList(baseStringParameters) );
if (debugOutput) {
qDebug() << "========== KQOAuthRequest has the following base string:";
qDebug() << baseString << "\n";
}
return baseString;
}
QByteArray KQOAuthRequestPrivate::encodedParamaterList(const QList< QPair<QString, QString> > &parameters) {
QByteArray resultList;
bool first = true;
QPair<QString, QString> parameter;
// Do the debug output.
if (debugOutput) {
qDebug() << "========== KQOAuthRequest has the following parameters:";
}
foreach (parameter, parameters) {
if(!first) {
resultList.append( "&" );
} else {
first = false;
}
// Here we don't need to explicitely encode the strings to UTF-8 since
// QUrl::toPercentEncoding() takes care of that for us.
resultList.append( QUrl::toPercentEncoding(parameter.first) // Parameter key
+ "="
+ QUrl::toPercentEncoding(parameter.second) // Parameter value
);
if (debugOutput) {
qDebug() << " * "
<< parameter.first
<< " : "
<< parameter.second;
}
}
if (debugOutput) {
qDebug() << "\n";
}
return QUrl::toPercentEncoding(resultList);
}
QString KQOAuthRequestPrivate::oauthTimestamp() const {
// This is basically for unit tests only. In most cases we don't set the nonce beforehand.
if (!oauthTimestamp_.isEmpty()) {
return oauthTimestamp_;
}
#if QT_VERSION >= 0x040700
return QString::number(QDateTime::currentDateTimeUtc().toTime_t());
#else
return QString::number(QDateTime::currentDateTime().toUTC().toTime_t());
#endif
}
QString KQOAuthRequestPrivate::oauthNonce() const {
// This is basically for unit tests only. In most cases we don't set the nonce beforehand.
if (!oauthNonce_.isEmpty()) {
return oauthNonce_;
}
return QString::number(qrand());
}
bool KQOAuthRequestPrivate::validateRequest() const {
switch ( requestType ) {
case KQOAuthRequest::TemporaryCredentials:
if (oauthRequestEndpoint.isEmpty()
|| oauthConsumerKey.isEmpty()
|| oauthNonce_.isEmpty()
|| oauthSignatureMethod.isEmpty()
|| oauthTimestamp_.isEmpty()
|| oauthVersion.isEmpty())
{
return false;
}
return true;
case KQOAuthRequest::AccessToken:
if (oauthRequestEndpoint.isEmpty()
|| oauthVerifier.isEmpty()
|| oauthConsumerKey.isEmpty()
|| oauthNonce_.isEmpty()
|| oauthSignatureMethod.isEmpty()
|| oauthTimestamp_.isEmpty()
|| oauthToken.isEmpty()
|| oauthTokenSecret.isEmpty()
|| oauthVersion.isEmpty())
{
return false;
}
return true;
case KQOAuthRequest::AuthorizedRequest:
if(requestOAuthMethod == KQOAuthRequest::OAUTH1) {
if (oauthRequestEndpoint.isEmpty()
|| oauthConsumerKey.isEmpty()
|| oauthNonce_.isEmpty()
|| oauthSignatureMethod.isEmpty()
|| oauthTimestamp_.isEmpty()
|| oauthToken.isEmpty()
|| oauthTokenSecret.isEmpty()
|| oauthVersion.isEmpty())
{
return false;
}
return true;
} else {
if(oauthToken.isEmpty()){
return false;
}
return true;
}
default:
return false;
}
// We should not come here.
return false;
}
//////////// Public implementation ////////////////
KQOAuthRequest::KQOAuthRequest(QObject *parent) :
QObject(parent),
d_ptr(new KQOAuthRequestPrivate)
{
d_ptr->debugOutput = false; // No debug output by default.
qsrand(QTime::currentTime().msec()); // We need to seed the nonce random number with something.
// However, we cannot do this while generating the nonce since
// we might get the same seed. So initializing here should be fine.
}
KQOAuthRequest::~KQOAuthRequest()
{
delete d_ptr;
}
void KQOAuthRequest::initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint) {
Q_D(KQOAuthRequest);
if (!requestEndpoint.isValid()) {
qWarning() << "Endpoint URL is not valid. Ignoring. This request might not work.";
return;
}
if (type < 0 || type > KQOAuthRequest::AuthorizedRequest) {
qWarning() << "Invalid request type. Ignoring. This request might not work.";
return;
}
// Clear the request
clearRequest();
// Set smart defaults.
d->requestType = type;
d->oauthRequestEndpoint = requestEndpoint;
d->oauthTimestamp_ = d->oauthTimestamp();
d->oauthNonce_ = d->oauthNonce();
this->setSignatureMethod(KQOAuthRequest::HMAC_SHA1);
this->setHttpMethod(KQOAuthRequest::POST);
d->oauthVersion = "1.0"; // Currently supports only version 1.0
d->contentType = "application/x-www-form-urlencoded";
}
void KQOAuthRequest::setConsumerKey(const QString &consumerKey) {
Q_D(KQOAuthRequest);
d->oauthConsumerKey = consumerKey;
}
void KQOAuthRequest::setConsumerSecretKey(const QString &consumerSecretKey) {
Q_D(KQOAuthRequest);
d->oauthConsumerSecretKey = consumerSecretKey;
}
void KQOAuthRequest::setCallbackUrl(const QUrl &callbackUrl) {
Q_D(KQOAuthRequest);
d->oauthCallbackUrl = callbackUrl;
}
void KQOAuthRequest::setSignatureMethod(KQOAuthRequest::RequestSignatureMethod requestMethod) {
Q_D(KQOAuthRequest);
QString requestMethodString;
switch (requestMethod) {
case KQOAuthRequest::PLAINTEXT:
requestMethodString = "PLAINTEXT";
break;
case KQOAuthRequest::HMAC_SHA1:
requestMethodString = "HMAC-SHA1";
break;
case KQOAuthRequest::RSA_SHA1:
requestMethodString = "RSA-SHA1";
break;
default:
// We should not come here
qWarning() << "Invalid signature method set.";
break;
}
d->oauthSignatureMethod = requestMethodString;
}
void KQOAuthRequest::setTokenSecret(const QString &tokenSecret) {
Q_D(KQOAuthRequest);
d->oauthTokenSecret = tokenSecret;
}
void KQOAuthRequest::setToken(const QString &token) {
Q_D(KQOAuthRequest);
d->oauthToken = token;
}
void KQOAuthRequest::setVerifier(const QString &verifier) {
Q_D(KQOAuthRequest);
d->oauthVerifier = verifier;
}
void KQOAuthRequest::setHttpMethod(KQOAuthRequest::RequestHttpMethod httpMethod) {
Q_D(KQOAuthRequest);
QString requestHttpMethodString;
switch (httpMethod) {
case KQOAuthRequest::GET:
requestHttpMethodString = "GET";
break;
case KQOAuthRequest::POST:
requestHttpMethodString = "POST";
break;
default:
qWarning() << "Invalid HTTP method set.";
break;
}
d->oauthHttpMethod = httpMethod;
d->oauthHttpMethodString = requestHttpMethodString;
}
void KQOAuthRequest::setRequestOAuthMethod(KQOAuthRequest::RequestOAuthMethod oauthMethod) {
Q_D(KQOAuthRequest);
d->requestOAuthMethod = oauthMethod;
}
KQOAuthRequest::RequestHttpMethod KQOAuthRequest::httpMethod() const {
Q_D(const KQOAuthRequest);
return d->oauthHttpMethod;
}
KQOAuthRequest::RequestOAuthMethod KQOAuthRequest::oauthMethod() const {
Q_D(const KQOAuthRequest);
return d->requestOAuthMethod;
}
void KQOAuthRequest::setAdditionalParameters(const KQOAuthParameters &additionalParams) {
Q_D(KQOAuthRequest);
QList<QString> additionalKeys = additionalParams.keys();
QList<QString> additionalValues = additionalParams.values();
int i=0;
foreach(QString key, additionalKeys) {
QString value = additionalValues.at(i);
d->additionalParameters.append( qMakePair(key, value) );
i++;
}
}
KQOAuthParameters KQOAuthRequest::additionalParameters() const {
Q_D(const KQOAuthRequest);
QMultiMap<QString, QString> additionalParams;
for(int i=0; i<d->additionalParameters.size(); i++) {
additionalParams.insert(d->additionalParameters.at(i).first,
d->additionalParameters.at(i).second);
}
if(d->requestOAuthMethod == KQOAuthRequest::OAUTH2) {
additionalParams.insert(OAUTH_KEY_TOKEN, d->oauthToken);
}
return additionalParams;
}
KQOAuthRequest::RequestType KQOAuthRequest::requestType() const {
Q_D(const KQOAuthRequest);
return d->requestType;
}
QUrl KQOAuthRequest::requestEndpoint() const {
Q_D(const KQOAuthRequest);
return d->oauthRequestEndpoint;
}
QList<QByteArray> KQOAuthRequest::requestParameters() {
Q_D(KQOAuthRequest);
QList<QByteArray> requestParamList;
d->prepareRequest();
if (!isValid() ) {
qWarning() << "Request is not valid! I will still sign it, but it will probably not work.";
}
if(d->requestOAuthMethod != KQOAuthRequest::OAUTH2) {
d->signRequest();
}
QPair<QString, QString> requestParam;
QString param;
QString value;
foreach (requestParam, d->requestParameters) {
param = requestParam.first;
value = requestParam.second;
requestParamList.append(QString(param + "=\"" + value +"\"").toUtf8());
}
return requestParamList;
}
QString KQOAuthRequest::contentType()
{
Q_D(const KQOAuthRequest);
return d->contentType;
}
void KQOAuthRequest::setContentType(const QString &contentType)
{
Q_D(KQOAuthRequest);
d->contentType = contentType;
}
QByteArray KQOAuthRequest::rawData()
{
Q_D(const KQOAuthRequest);
return d->postRawData;
}
void KQOAuthRequest::setRawData(const QByteArray &rawData)
{
Q_D(KQOAuthRequest);
d->postRawData = rawData;
}
QByteArray KQOAuthRequest::requestBody() const {
Q_D(const KQOAuthRequest);
QByteArray postBodyContent;
bool first = true;
for(int i=0; i < d->additionalParameters.size(); i++) {
if(!first) {
postBodyContent.append("&");
} else {
first = false;
}
QString key = d->additionalParameters.at(i).first;
QString value = d->additionalParameters.at(i).second;
postBodyContent.append(QUrl::toPercentEncoding(key) + QString("=").toUtf8() +
QUrl::toPercentEncoding(value));
}
qDebug() << postBodyContent;
return postBodyContent;
}
bool KQOAuthRequest::isValid() const {
Q_D(const KQOAuthRequest);
return d->validateRequest();
}
void KQOAuthRequest::setTimeout(int timeoutMilliseconds) {
Q_D(KQOAuthRequest);
d->timeout = timeoutMilliseconds;
}
void KQOAuthRequest::clearRequest() {
Q_D(KQOAuthRequest);
d->oauthRequestEndpoint = "";
d->oauthHttpMethodString = "";
d->oauthConsumerKey = "";
d->oauthConsumerSecretKey = "";
d->oauthToken = "";
d->oauthTokenSecret = "";
d->oauthSignatureMethod = "";
d->oauthCallbackUrl = "";
d->oauthVerifier = "";
d->oauthTimestamp_ = "";
d->oauthNonce_ = "";
d->requestParameters.clear();
d->additionalParameters.clear();
d->timeout = 0;
}
void KQOAuthRequest::setEnableDebugOutput(bool enabled) {
Q_D(KQOAuthRequest);
d->debugOutput = enabled;
}
/**
* Protected implementations for inherited classes
*/
bool KQOAuthRequest::validateXAuthRequest() const {
Q_D(const KQOAuthRequest);
if (d->oauthRequestEndpoint.isEmpty()
|| d->oauthConsumerKey.isEmpty()
|| d->oauthNonce_.isEmpty()
|| d->oauthSignatureMethod.isEmpty()
|| d->oauthTimestamp_.isEmpty()
|| d->oauthVersion.isEmpty())
{
return false;
}
return true;
}
bool KQOAuthRequest::validateOauth2Request() const {
Q_D(const KQOAuthRequest);
if (d->oauthRequestEndpoint.isEmpty()
|| d->oauthConsumerKey.isEmpty()
|| d->oauthConsumerSecretKey.isEmpty())
{
return false;
}
return true;
}
/**
* Private implementations for friend classes
*/
QString KQOAuthRequest::consumerKeyForManager() const {
Q_D(const KQOAuthRequest);
return d->oauthConsumerKey;
}
QString KQOAuthRequest::consumerKeySecretForManager() const {
Q_D(const KQOAuthRequest);
return d->oauthConsumerSecretKey;
}
QUrl KQOAuthRequest::callbackUrlForManager() const {
Q_D(const KQOAuthRequest);
return d->oauthCallbackUrl;
}
void KQOAuthRequest::requestTimerStart()
{
Q_D(KQOAuthRequest);
if (d->timeout > 0) {
connect(&(d->timer), SIGNAL(timeout()), this, SIGNAL(requestTimedout()));
d->timer.start(d->timeout);
}
}
void KQOAuthRequest::requestTimerStop()
{
Q_D(KQOAuthRequest);
if (d->timeout > 0) {
disconnect(&(d->timer), SIGNAL(timeout()), this, SIGNAL(requestTimedout()));
d->timer.stop();
}
}

153
oauth/kqoauthrequest.h Normal file
View file

@ -0,0 +1,153 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHREQUEST_H
#define KQOAUTHREQUEST_H
#include <QObject>
#include <QUrl>
#include <QMultiMap>
#include "kqoauthglobals.h"
typedef QMultiMap<QString, QString> KQOAuthParameters;
class KQOAuthRequestPrivate;
class KQOAUTH_EXPORT KQOAuthRequest : public QObject
{
Q_OBJECT
public:
explicit KQOAuthRequest(QObject *parent = 0);
~KQOAuthRequest();
enum RequestType {
TemporaryCredentials = 0,
AccessToken,
AuthorizedRequest
};
enum RequestSignatureMethod {
PLAINTEXT = 0,
HMAC_SHA1,
RSA_SHA1
};
enum RequestHttpMethod {
GET = 0,
POST
};
enum RequestOAuthMethod {
OAUTH1 = 0,
OAUTH2
};
/**
* These methods can be overridden in child classes which are different types of
* OAuth requests.
*/
// Validate the request of this type.
virtual bool isValid() const;
/**
* These methods are OAuth request type specific and not overridden in child
* classes.
* NOTE: Refactorting still a TODO
*/
// Initialize the request of this type.
virtual void initRequest(KQOAuthRequest::RequestType type, const QUrl &requestEndpoint);
void setConsumerKey(const QString &consumerKey);
void setConsumerSecretKey(const QString &consumerSecretKey);
// Mandatory methods for acquiring a request token
void setCallbackUrl(const QUrl &callbackUrl);
// Mandator methods for acquiring a access token
void setTokenSecret(const QString &tokenSecret);
void setToken(const QString &token);
void setVerifier(const QString &verifier);
// Request signature method to use - HMAC_SHA1 currently only supported
void setSignatureMethod(KQOAuthRequest::RequestSignatureMethod = KQOAuthRequest::HMAC_SHA1);
// Request's HTTP method.
void setHttpMethod(KQOAuthRequest::RequestHttpMethod = KQOAuthRequest::POST);
KQOAuthRequest::RequestHttpMethod httpMethod() const;
KQOAuthRequest::RequestOAuthMethod oauthMethod() const;
void setRequestOAuthMethod(KQOAuthRequest::RequestOAuthMethod = KQOAuthRequest::OAUTH1);
// Sets the timeout for this request. If the timeout expires, signal "requestTimedout" will be
// emitted from the manager.
// 0 = If set to zero, timeout is disabled.
// TODO: Do we need some request ID now?
void setTimeout(int timeoutMilliseconds);
// Additional optional parameters to the request.
void setAdditionalParameters(const KQOAuthParameters &additionalParams);
KQOAuthParameters additionalParameters() const;
QList<QByteArray> requestParameters(); // This will return all request's parameters in the raw format given
// to the QNetworkRequest.
QByteArray requestBody() const; // This will return the POST body as given to the QNetworkRequest.
KQOAuthRequest::RequestType requestType() const;
QUrl requestEndpoint() const;
void setContentType(const QString &contentType);
QString contentType();
void setRawData(const QByteArray &rawData);
QByteArray rawData();
void clearRequest();
// Enable verbose debug output for request content.
void setEnableDebugOutput(bool enabled);
Q_SIGNALS:
// This signal is emited if the request is not completed before the request's timeout
// value has expired.
void requestTimedout();
protected:
bool validateXAuthRequest() const;
bool validateOauth2Request() const;
private:
KQOAuthRequestPrivate * const d_ptr;
Q_DECLARE_PRIVATE(KQOAuthRequest);
Q_DISABLE_COPY(KQOAuthRequest);
// These classes are only for the internal use of KQOAuthManager so it can
// work with the opaque request.
QString consumerKeyForManager() const;
QString consumerKeySecretForManager() const;
QUrl callbackUrlForManager() const;
// This method is for timeout handling by the KQOAuthManager.
void requestTimerStart();
void requestTimerStop();
friend class KQOAuthManager;
#ifdef UNIT_TEST
friend class Ut_KQOAuth;
#endif
};
#endif // KQOAUTHREQUEST_H

View file

@ -0,0 +1,5 @@
#include "kqoauthrequest_1.h"
KQOAuthRequest_1::KQOAuthRequest_1()
{
}

12
oauth/kqoauthrequest_1.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef KQOAUTHREQUEST_1_H
#define KQOAUTHREQUEST_1_H
#include "kqoauthrequest.h"
class KQOAUTH_EXPORT KQOAuthRequest_1 : public KQOAuthRequest
{
public:
KQOAuthRequest_1();
};
#endif // KQOAUTHREQUEST_1_H

94
oauth/kqoauthrequest_p.h Normal file
View file

@ -0,0 +1,94 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHREQUEST_P_H
#define KQOAUTHREQUEST_P_H
#include "kqoauthglobals.h"
#include "kqoauthrequest.h"
#include <QString>
#include <QUrl>
#include <QMap>
#include <QPair>
#include <QMultiMap>
#include <QTimer>
class KQOAUTH_EXPORT KQOAuthRequestPrivate {
public:
KQOAuthRequestPrivate();
~KQOAuthRequestPrivate();
// Helper methods to get the values for the OAuth request parameters.
QString oauthTimestamp() const;
QString oauthNonce() const;
QString oauthSignature();
// Utility methods for making the request happen.
void prepareRequest();
void signRequest();
bool validateRequest() const;
QByteArray requestBaseString();
QByteArray encodedParamaterList(const QList< QPair<QString, QString> > &requestParameters);
void insertAdditionalParams();
void insertPostBody();
QUrl oauthRequestEndpoint;
KQOAuthRequest::RequestHttpMethod oauthHttpMethod;
QString oauthHttpMethodString;
QString oauthConsumerKey;
QString oauthConsumerSecretKey;
QString oauthToken;
QString oauthTokenSecret;
QString oauthSignatureMethod;
QUrl oauthCallbackUrl;
QString oauthVersion;
QString oauthVerifier;
// These will be generated by the helper methods
QString oauthTimestamp_;
QString oauthNonce_;
// User specified additional parameters needed for the request.
QList< QPair<QString, QString> > additionalParameters;
// The raw POST body content as given to the HTTP request.
QByteArray postBodyContent;
// Protocol parameters.
// These parameters are used in the "Authorized" header of the HTTP request.
QList< QPair<QString, QString> > requestParameters;
KQOAuthRequest::RequestType requestType;
KQOAuthRequest::RequestOAuthMethod requestOAuthMethod;
//The Content-Type HTTP header
QString contentType;
//Raw data to post if type is not url-encoded
QByteArray postRawData;
// Timeout for this request in milliseconds.
int timeout;
QTimer timer;
bool debugOutput;
};
#endif // KQOAUTHREQUEST_P_H

View file

@ -0,0 +1,91 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QtDebug>
#include "kqoauthrequest_xauth_p.h"
#include "kqoauthrequest_xauth.h"
/**
* Private d_ptr implementations.
*/
KQOAuthRequest_XAuthPrivate::KQOAuthRequest_XAuthPrivate()
{
}
KQOAuthRequest_XAuthPrivate::~KQOAuthRequest_XAuthPrivate()
{
}
/**
* Public implementations.
*/
KQOAuthRequest_XAuth::KQOAuthRequest_XAuth(QObject *parent) :
KQOAuthRequest(parent),
d_ptr(new KQOAuthRequest_XAuthPrivate)
{
}
bool KQOAuthRequest_XAuth::isValid() const {
// An xAuth can never request temporary credentials.
if (requestType() == KQOAuthRequest::TemporaryCredentials) {
qWarning() << "XAuth request cannot be of type KQOAuthRequest::TemporaryCredentials. Aborting.";
return false;
}
// Access token must always be retrieved using the POST HTTP method.
if (requestType() == KQOAuthRequest::AccessToken
&& httpMethod() != KQOAuthRequest::POST) {
qWarning() << "Access tokens must be fetched using the POST HTTP method. Aborting.";
return false;
}
if (!xauth_parameters_set) {
qWarning() << "No XAuth parameters set. Aborting.";
return false;
}
// And then check the validity of the XAuth request.
// Provided by the base class as a protected method for us.
return validateXAuthRequest();
}
void KQOAuthRequest_XAuth::setXAuthLogin(const QString &username,
const QString &password) {
if (username.isEmpty() || password.isEmpty()) {
qWarning() << "Username or password cannot be empty. Aborting.";
return;
}
xauth_parameters_set = true;
qDebug() << username << password;
KQOAuthParameters xauthParams;
xauthParams.insert("x_auth_username", username);
xauthParams.insert("x_auth_password", password);
xauthParams.insert("x_auth_mode", "client_auth");
setAdditionalParameters(xauthParams);
}

View file

@ -0,0 +1,49 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHREQUEST_XAUTH_H
#define KQOAUTHREQUEST_XAUTH_H
#include "kqoauthrequest.h"
#include "kqoauthrequest_1.h"
class KQOAuthRequest_XAuthPrivate;
class KQOAUTH_EXPORT KQOAuthRequest_XAuth : public KQOAuthRequest
{
Q_OBJECT
public:
KQOAuthRequest_XAuth(QObject *parent = 0);
/**
* These methods can be overridden in child classes which are different types of
* OAuth requests.
*/
// Validate the request of this type.
bool isValid() const;
// Give the xAuth specific parameters.
void setXAuthLogin(const QString &username = "",
const QString &password = "");
private:
KQOAuthRequest_XAuthPrivate * const d_ptr;
bool xauth_parameters_set;
};
#endif // KQOAUTHREQUEST_XAUTH_H

View file

@ -0,0 +1,14 @@
#ifndef KQOAUTHREQUEST_XAUTH_P_H
#define KQOAUTHREQUEST_XAUTH_P_H
#include "kqoauthglobals.h"
class KQOAuthRequest;
class KQOAUTH_EXPORT KQOAuthRequest_XAuthPrivate
{
public:
KQOAuthRequest_XAuthPrivate();
~KQOAuthRequest_XAuthPrivate();
};
#endif // KQOAUTHREQUEST_XAUTH_P_H

79
oauth/kqoauthutils.cpp Normal file
View file

@ -0,0 +1,79 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QString>
#include <QCryptographicHash>
#include <QByteArray>
#include <QtDebug>
#include "kqoauthutils.h"
QString KQOAuthUtils::hmac_sha1(const QString &message, const QString &key)
{
QByteArray keyBytes = key.toAscii();
int keyLength; // Lenght of key word
const int blockSize = 64; // Both MD5 and SHA-1 have a block size of 64.
keyLength = keyBytes.size();
// If key is longer than block size, we need to hash the key
if (keyLength > blockSize) {
QCryptographicHash hash(QCryptographicHash::Sha1);
hash.addData(keyBytes);
keyBytes = hash.result();
}
/* http://tools.ietf.org/html/rfc2104 - (1) */
// Create the opad and ipad for the hash function.
QByteArray ipad;
QByteArray opad;
ipad.fill( 0, blockSize);
opad.fill( 0, blockSize);
ipad.replace(0, keyBytes.length(), keyBytes);
opad.replace(0, keyBytes.length(), keyBytes);
/* http://tools.ietf.org/html/rfc2104 - (2) & (5) */
for (int i=0; i<64; i++) {
ipad[i] = ipad[i] ^ 0x36;
opad[i] = opad[i] ^ 0x5c;
}
QByteArray workArray;
workArray.clear();
workArray.append(ipad, 64);
/* http://tools.ietf.org/html/rfc2104 - (3) */
workArray.append(message.toAscii());
/* http://tools.ietf.org/html/rfc2104 - (4) */
QByteArray sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
/* http://tools.ietf.org/html/rfc2104 - (6) */
workArray.clear();
workArray.append(opad, 64);
workArray.append(sha1);
sha1.clear();
/* http://tools.ietf.org/html/rfc2104 - (7) */
sha1 = QCryptographicHash::hash(workArray, QCryptographicHash::Sha1);
return QString(sha1.toBase64());
}

33
oauth/kqoauthutils.h Normal file
View file

@ -0,0 +1,33 @@
/**
* KQOAuth - An OAuth authentication library for Qt.
*
* Author: Johan Paul (johan.paul@d-pointer.com)
* http://www.d-pointer.com
*
* KQOAuth is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KQOAuth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with KQOAuth. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KQOAUTHUTILS_H
#define KQOAUTHUTILS_H
#include "kqoauthglobals.h"
class QString;
class KQOAUTH_EXPORT KQOAuthUtils
{
public:
static QString hmac_sha1(const QString &message, const QString &key);
};
#endif // KQOAUTHUTILS_H