diff --git a/QtOAuth/private/qabstractoauth_p.h b/QtOAuth/private/qabstractoauth_p.h index 385b15e86e5d689785082188dfc754e9d0b0d19e..a5c41fa20bb64ffeefe98cf21720a7d7dde64ac0 100644 --- a/QtOAuth/private/qabstractoauth_p.h +++ b/QtOAuth/private/qabstractoauth_p.h @@ -80,6 +80,7 @@ public: QNetworkAccessManager *networkAccessManager(); void setStatus(QAbstractOAuth::Status status); + // Resource Owner Authorization: https://tools.ietf.org/html/rfc5849#section-2.2 QUrl authorizationUrl; QVariantMap extraTokens; QAbstractOAuth::Status status = QAbstractOAuth::Status::NotAuthenticated; diff --git a/QtOAuth/private/qoauth1_p.h b/QtOAuth/private/qoauth1_p.h index 658dfa157e151853609818311b31b413c6ab5f55..8853f66f944106892bf3a81990c299a5639315ee 100644 --- a/QtOAuth/private/qoauth1_p.h +++ b/QtOAuth/private/qoauth1_p.h @@ -83,7 +83,6 @@ public: // private slots void _q_onTokenRequestFinished(); void _q_onTokenRequestError(QNetworkReply::NetworkError error); - void _q_onTokenExchangeError(QNetworkReply::NetworkError error); void _q_requestAuthorizationGrantAnswer(); void _q_tokensReceived(const QVariantMap &tokens); diff --git a/QtOAuth/private/qoauth2authorizationcodeflow_p.h b/QtOAuth/private/qoauth2authorizationcodeflow_p.h index d1a172971e4ecad7950e7f58b030adea4d4f6a16..d07ff9ef1a8bf2d6bd7d8bee963f986ee5113089 100644 --- a/QtOAuth/private/qoauth2authorizationcodeflow_p.h +++ b/QtOAuth/private/qoauth2authorizationcodeflow_p.h @@ -69,9 +69,9 @@ class OAUTH_EXPORT QOAuth2AuthorizationCodeFlowPrivate : public QAbstractOAuth2P public: QOAuth2AuthorizationCodeFlowPrivate(QNetworkAccessManager *manager = nullptr); - void handleCallback(const QVariantMap &data); - void accessTokenRequestFinished(QNetworkReply *reply); - void authenticate(QNetworkReply *reply, QAuthenticator *authenticator); + void _q_handleCallback(const QVariantMap &data); + void _q_accessTokenRequestFinished(QNetworkReply *reply); + void _q_authenticate(QNetworkReply *reply, QAuthenticator *authenticator); QUrl accessTokenUrl; QString tokenType; diff --git a/QtOAuth/private/qoauthhttpserverreplyhandler_p.h b/QtOAuth/private/qoauthhttpserverreplyhandler_p.h index 82dd0ade3af9f9fb95ee77a9fc027b04e9d4e685..93c20303162d7617ef6be0edc57bce700c6802aa 100644 --- a/QtOAuth/private/qoauthhttpserverreplyhandler_p.h +++ b/QtOAuth/private/qoauthhttpserverreplyhandler_p.h @@ -73,8 +73,8 @@ public: QString text; private: - void onClientConnected(); - void answerClient(); + void _q_clientConnected(); + void _q_answerClient(); }; QT_END_NAMESPACE diff --git a/QtOAuth/qabstractoauth.cpp b/QtOAuth/qabstractoauth.cpp index 9c7e3795bd11d371a4a097a5f4b5700ae38894bc..9c3933cf2ba20b5d9d7c5545ee7b7afb91e5dd32 100644 --- a/QtOAuth/qabstractoauth.cpp +++ b/QtOAuth/qabstractoauth.cpp @@ -186,6 +186,13 @@ QString QAbstractOAuth::callback() const : d->defaultReplyHandler->callback(); } +void QAbstractOAuth::resourceOwnerAuthorization(const QUrl &url, const QVariantMap ¶meters) +{ + QUrl u = url; + u.setQuery(QAbstractOAuthPrivate::createQuery(parameters)); + Q_EMIT authorizeWithBrowser(u); +} + QT_END_NAMESPACE #endif // QT_NO_HTTP diff --git a/QtOAuth/qabstractoauth.h b/QtOAuth/qabstractoauth.h index 8b411fbc6309c04e23eeeee6002c37509330e914..ffaa68c5a3099e514ae0be59eb5ab98c7d1b3f0b 100644 --- a/QtOAuth/qabstractoauth.h +++ b/QtOAuth/qabstractoauth.h @@ -116,7 +116,6 @@ public: Status status() const; - // Resource Owner Authorization: https://tools.ietf.org/html/rfc5849#section-2.2 QUrl authorizationUrl() const; void setAuthorizationUrl(const QUrl &url); @@ -148,7 +147,7 @@ Q_SIGNALS: void extraTokensChanged(const QVariantMap &tokens); void requestFailed(const Error error); - void authorizationRequested(const QUrl &url); + void authorizeWithBrowser(const QUrl &url); void granted(); void finished(QNetworkReply *reply); void replyDataReceived(const QByteArray &data); @@ -160,6 +159,8 @@ protected: QString callback() const; + virtual void resourceOwnerAuthorization(const QUrl &url, const QVariantMap ¶meters); + private: Q_DISABLE_COPY(QAbstractOAuth) Q_DECLARE_PRIVATE(QAbstractOAuth) diff --git a/QtOAuth/qoauth1.cpp b/QtOAuth/qoauth1.cpp index 936a56a9ba72630393a26d6d2550449caa465780..59660a61eab8e05756f3ed8048aae1632a517a01 100644 --- a/QtOAuth/qoauth1.cpp +++ b/QtOAuth/qoauth1.cpp @@ -87,12 +87,6 @@ void QOAuth1Private::_q_onTokenRequestError(QNetworkReply::NetworkError error) Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); } -void QOAuth1Private::_q_onTokenExchangeError(QNetworkReply::NetworkError) -{ - Q_Q(QOAuth1); - Q_EMIT q->requestFailed(QAbstractOAuth::Error::NetworkError); -} - void QOAuth1Private::_q_requestAuthorizationGrantAnswer() { Q_Q(QOAuth1); @@ -504,6 +498,7 @@ QNetworkReply *QOAuth1::requestTemporaryCredentials(QNetworkAccessManager::Opera const QUrl &url, const QVariantMap ¶meters) { + // https://tools.ietf.org/html/rfc5849#section-2.1 Q_D(QOAuth1); if (Q_UNLIKELY(!d->networkAccessManager())) { qCritical("QNetworkAccessManager not available"); @@ -653,6 +648,7 @@ QByteArray QOAuth1::signatureBaseString(const QVariantMap ¶meters, const QUrl &url, QNetworkAccessManager::Operation op) { + // https://tools.ietf.org/html/rfc5849#section-3.4.1 QByteArray base; base.append(QOAuth1Private::operationName(op).toUtf8() + "&"); @@ -733,9 +729,8 @@ void QOAuth1::grant() if (d->modifyParametersFunction) d->modifyParametersFunction(Stage::RequestingAuthorization, ¶meters); - QUrl url = d->authorizationUrl; - url.setQuery(QAbstractOAuthPrivate::createQuery(parameters)); - Q_EMIT authorizationRequested(url); + // https://tools.ietf.org/html/rfc5849#section-2.2 + resourceOwnerAuthorization(d->authorizationUrl, parameters); } else { // try upgrading token without verifier diff --git a/QtOAuth/qoauth2authorizationcodeflow.cpp b/QtOAuth/qoauth2authorizationcodeflow.cpp index d6c95588c3c1a7a872a539393ae4467f125c4aad..a2f2d927aeb69f697d0a52a0609d2b7f10af0bab 100644 --- a/QtOAuth/qoauth2authorizationcodeflow.cpp +++ b/QtOAuth/qoauth2authorizationcodeflow.cpp @@ -59,7 +59,7 @@ QOAuth2AuthorizationCodeFlowPrivate::QOAuth2AuthorizationCodeFlowPrivate( QNetworkAccessManager *manager) : QAbstractOAuth2Private(manager) {} -void QOAuth2AuthorizationCodeFlowPrivate::handleCallback(const QVariantMap &data) +void QOAuth2AuthorizationCodeFlowPrivate::_q_handleCallback(const QVariantMap &data) { Q_Q(QOAuth2AuthorizationCodeFlow); typedef QAbstractOAuth2Private::OAuth2KeyString Key; @@ -99,7 +99,7 @@ void QOAuth2AuthorizationCodeFlowPrivate::handleCallback(const QVariantMap &data q->requestAccessToken(code); } -void QOAuth2AuthorizationCodeFlowPrivate::accessTokenRequestFinished(QNetworkReply *reply) +void QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished(QNetworkReply *reply) { Q_Q(QOAuth2AuthorizationCodeFlow); typedef QAbstractOAuth2Private::OAuth2KeyString Key; @@ -146,7 +146,7 @@ void QOAuth2AuthorizationCodeFlowPrivate::accessTokenRequestFinished(QNetworkRep setStatus(QAbstractOAuth::Status::Granted); } -void QOAuth2AuthorizationCodeFlowPrivate::authenticate(QNetworkReply *reply, +void QOAuth2AuthorizationCodeFlowPrivate::_q_authenticate(QNetworkReply *reply, QAuthenticator *authenticator) { if (reply == currentReply){ @@ -234,10 +234,7 @@ void QOAuth2AuthorizationCodeFlow::grant() return; } - const QUrl url = buildAuthenticateUrl(); - QObjectPrivate::connect(this, &QOAuth2AuthorizationCodeFlow::authorizationCallbackReceived, d, - &QOAuth2AuthorizationCodeFlowPrivate::handleCallback); - Q_EMIT authorizationRequested(url); + resourceOwnerAuthorization(d->authorizationUrl); } void QOAuth2AuthorizationCodeFlow::refreshAccessToken() @@ -266,10 +263,10 @@ void QOAuth2AuthorizationCodeFlow::refreshAccessToken() d->currentReply = d->networkAccessManager()->post(request, data.toUtf8()); QObjectPrivate::connect(d->networkAccessManager(), &QNetworkAccessManager::finished, - d, &QOAuth2AuthorizationCodeFlowPrivate::accessTokenRequestFinished); + d, &QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished); QObjectPrivate::connect(d->networkAccessManager(), &QNetworkAccessManager::authenticationRequired, - d, &QOAuth2AuthorizationCodeFlowPrivate::authenticate, + d, &QOAuth2AuthorizationCodeFlowPrivate::_q_authenticate, Qt::UniqueConnection); } @@ -294,9 +291,9 @@ QUrl QOAuth2AuthorizationCodeFlow::buildAuthenticateUrl(const QVariantMap ¶m d->modifyParametersFunction(Stage::RequestingAuthorization, &p); url.setQuery(d->createQuery(p)); connect(d->replyHandler.data(), &QAbstractOAuthReplyHandler::callbackReceived, this, - &QOAuth2AuthorizationCodeFlow::authorizationCallbackReceived); + &QOAuth2AuthorizationCodeFlow::authorizationCallbackReceived, Qt::UniqueConnection); setStatus(QAbstractOAuth::Status::NotAuthenticated); - qDebug() << url; + qDebug("QOAuth2AuthorizationCodeFlow::buildAuthenticateUrl: %s", qPrintable(url.toString())); return url; } @@ -323,11 +320,23 @@ void QOAuth2AuthorizationCodeFlow::requestAccessToken(const QString &code) const QString data = query.toString(QUrl::FullyEncoded); d->currentReply = d->networkAccessManager()->post(request, data.toUtf8()); QObjectPrivate::connect(d->networkAccessManager(), &QNetworkAccessManager::finished, - d, &QOAuth2AuthorizationCodeFlowPrivate::accessTokenRequestFinished); + d, &QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished); QObjectPrivate::connect(d->networkAccessManager(), &QNetworkAccessManager::authenticationRequired, - d, &QOAuth2AuthorizationCodeFlowPrivate::authenticate, + d, &QOAuth2AuthorizationCodeFlowPrivate::_q_authenticate, + Qt::UniqueConnection); +} + +void QOAuth2AuthorizationCodeFlow::resourceOwnerAuthorization(const QUrl &url, + const QVariantMap ¶meters) +{ + Q_D(QOAuth2AuthorizationCodeFlow); + Q_ASSERT(url == d->authorizationUrl); + const QUrl u = buildAuthenticateUrl(parameters); + QObjectPrivate::connect(this, &QOAuth2AuthorizationCodeFlow::authorizationCallbackReceived, d, + &QOAuth2AuthorizationCodeFlowPrivate::_q_handleCallback, Qt::UniqueConnection); + Q_EMIT authorizeWithBrowser(u); } QT_END_NAMESPACE diff --git a/QtOAuth/qoauth2authorizationcodeflow.h b/QtOAuth/qoauth2authorizationcodeflow.h index 5cd2df5e2492d51066b3bff22868d7e2776491cc..c1a274fa8f886afc7eb9a9a02ef024caf51fa571 100644 --- a/QtOAuth/qoauth2authorizationcodeflow.h +++ b/QtOAuth/qoauth2authorizationcodeflow.h @@ -93,6 +93,8 @@ public Q_SLOTS: protected: QUrl buildAuthenticateUrl(const QVariantMap ¶meters = QVariantMap()); void requestAccessToken(const QString &code); + virtual void resourceOwnerAuthorization(const QUrl &url, + const QVariantMap ¶meters = QVariantMap()) override; Q_SIGNALS: void accessTokenUrlChanged(const QUrl &accessTokenUrl); diff --git a/QtOAuth/qoauth2implicitgrantflow.cpp b/QtOAuth/qoauth2implicitgrantflow.cpp index d5c3ba8a4678f968d68ec3c6d2c3d1e167885e20..a3eb9f0e5833f1aea8b85e8e55ac470a4acf7637 100644 --- a/QtOAuth/qoauth2implicitgrantflow.cpp +++ b/QtOAuth/qoauth2implicitgrantflow.cpp @@ -90,7 +90,7 @@ void QOAuth2ImplicitGrantFlow::grant() { const QString state = QAbstractOAuth2Private::generateRandomState(); const QUrl url = authorizationRequestUrl(state); - Q_EMIT authorizationRequested(url); + Q_EMIT authorizeWithBrowser(url); } QUrl QOAuth2ImplicitGrantFlow::authorizationRequestUrl(const QString &state) const diff --git a/QtOAuth/qoauthhttpserverreplyhandler.cpp b/QtOAuth/qoauthhttpserverreplyhandler.cpp index 7f8066ee048b7667f7c6c16f7305a6720fd3a791..d769e03c5ac10d6fd20331821ed8461e7548a675 100644 --- a/QtOAuth/qoauthhttpserverreplyhandler.cpp +++ b/QtOAuth/qoauthhttpserverreplyhandler.cpp @@ -64,16 +64,16 @@ QOAuthHttpServerReplyHandlerPrivate::QOAuthHttpServerReplyHandlerPrivate(quint16 QOAuthHttpServerReplyHandlerPrivate::~QOAuthHttpServerReplyHandlerPrivate() {} -void QOAuthHttpServerReplyHandlerPrivate::onClientConnected() +void QOAuthHttpServerReplyHandlerPrivate::_q_clientConnected() { QTcpSocket *socket = httpServer.nextPendingConnection(); QObject::connect(socket, &QTcpSocket::disconnected, socket, &QTcpSocket::deleteLater); connect(socket, &QTcpSocket::readyRead, - this, &QOAuthHttpServerReplyHandlerPrivate::answerClient); + this, &QOAuthHttpServerReplyHandlerPrivate::_q_answerClient); } -void QOAuthHttpServerReplyHandlerPrivate::answerClient() +void QOAuthHttpServerReplyHandlerPrivate::_q_answerClient() { Q_Q(QOAuthHttpServerReplyHandler); QTcpSocket *socket = static_cast(currentSender->sender); @@ -108,7 +108,7 @@ QOAuthHttpServerReplyHandler::QOAuthHttpServerReplyHandler(QObject *parent) { Q_D(QOAuthHttpServerReplyHandler); d->connect(&d->httpServer, &QTcpServer::newConnection, - d, &QOAuthHttpServerReplyHandlerPrivate::onClientConnected); + d, &QOAuthHttpServerReplyHandlerPrivate::_q_clientConnected); } QOAuthHttpServerReplyHandler::QOAuthHttpServerReplyHandler(quint16 port, QObject *parent) @@ -116,7 +116,7 @@ QOAuthHttpServerReplyHandler::QOAuthHttpServerReplyHandler(quint16 port, QObject { Q_D(QOAuthHttpServerReplyHandler); d->connect(&d->httpServer, &QTcpServer::newConnection, - d, &QOAuthHttpServerReplyHandlerPrivate::onClientConnected); + d, &QOAuthHttpServerReplyHandlerPrivate::_q_clientConnected); } QOAuthHttpServerReplyHandler::~QOAuthHttpServerReplyHandler() diff --git a/examples/googlecalendar/main.qml b/examples/googlecalendar/main.qml index eccf85e19afa11f2ee9c124cbe53bda6af0f9940..525ecbb4c8d65e725c63fe0160ad6b79254e07e2 100644 --- a/examples/googlecalendar/main.qml +++ b/examples/googlecalendar/main.qml @@ -124,8 +124,9 @@ ApplicationWindow { scope: "https://www.googleapis.com/auth/calendar.readonly" port: 1965 - onAuthorizationRequested: { + onAuthorizeWithBrowser: { webView.url = url; + console.log("Url: " + url); webView.visible = true; } Component.onCompleted: grant(); diff --git a/examples/qtgcal/main.cpp b/examples/qtgcal/main.cpp index 3564701730f1636ba61f8756a6887a4c10e36ced..5e3722db22c0e8184cb38dcb27d06f313960434c 100644 --- a/examples/qtgcal/main.cpp +++ b/examples/qtgcal/main.cpp @@ -111,7 +111,7 @@ int main(int argc, char **argv) parameters->insert("grant_type", "authorization_code"); } }); - QObject::connect(&o2, &QOAuth2AuthorizationCodeFlow::authorizationRequested, + QObject::connect(&o2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl); QNetworkReply *reply = nullptr; diff --git a/examples/redditclient/redditwrapper.cpp b/examples/redditclient/redditwrapper.cpp index 8d367f3bfcce64ea34e182764e26ddd808918ed7..1f2af93685bb6d64c3b5c04baf289000cd7e45b1 100644 --- a/examples/redditclient/redditwrapper.cpp +++ b/examples/redditclient/redditwrapper.cpp @@ -65,7 +65,7 @@ RedditWrapper::RedditWrapper(QObject *parent) if (stage == QAbstractOAuth::Stage::RequestingAuthorization && isPermanent()) parameters->insert("duration", "permanent"); }); - connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizationRequested, + connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl); } diff --git a/examples/twittertimeline/twitter.cpp b/examples/twittertimeline/twitter.cpp index ba336a62ce4a9b8c25aa2a8b03e340a16b5d1770..7d3a4d067d295cd4134f15402e089bfb67be1562 100644 --- a/examples/twittertimeline/twitter.cpp +++ b/examples/twittertimeline/twitter.cpp @@ -52,7 +52,7 @@ Twitter::Twitter(QObject *parent) : setAuthorizationUrl(QUrl("https://api.twitter.com/oauth/authenticate")); setTokenCredentialsUrl(QUrl("https://api.twitter.com/oauth/access_token")); - connect(this, &QAbstractOAuth::authorizationRequested, [&](QUrl url) { + connect(this, &QAbstractOAuth::authorizeWithBrowser, [&](QUrl url) { QUrlQuery query(url); query.addQueryItem("force_login", "true"); // Forces the user to enter their credentials to