| /**************************************************************************** |
| ** |
| ** Copyright (C) 2017 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the test suite of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU General Public License Usage |
| ** Alternatively, this file may be used under the terms of the GNU |
| ** General Public License version 3 as published by the Free Software |
| ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
| ** included in the packaging of this file. Please review the following |
| ** information to ensure the GNU General Public License requirements will |
| ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
| ** |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| #include <QtTest> |
| |
| #include <QtNetworkAuth/qabstractoauthreplyhandler.h> |
| #include <QtNetworkAuth/qoauth2authorizationcodeflow.h> |
| |
| #include "webserver.h" |
| |
| class tst_OAuth2 : public QObject |
| { |
| Q_OBJECT |
| |
| private Q_SLOTS: |
| void getToken(); |
| void refreshToken(); |
| void getAndRefreshToken(); |
| void prepareRequest(); |
| }; |
| |
| struct ReplyHandler : QAbstractOAuthReplyHandler |
| { |
| QString callback() const override |
| { |
| return QLatin1String("test"); |
| } |
| |
| void networkReplyFinished(QNetworkReply *reply) override |
| { |
| QVariantMap data; |
| const auto items = QUrlQuery(reply->readAll()).queryItems(); |
| for (const auto &pair : items) |
| data.insert(pair.first, pair.second); |
| Q_EMIT tokensReceived(data); |
| } |
| |
| void emitCallbackReceived(const QVariantMap &data) |
| { |
| Q_EMIT callbackReceived(data); |
| } |
| }; |
| |
| void tst_OAuth2::getToken() |
| { |
| WebServer webServer([](const WebServer::HttpRequest &request, QTcpSocket *socket) { |
| if (request.url.path() == QLatin1String("/accessToken")) { |
| const QString text = "access_token=token&token_type=bearer"; |
| const QByteArray replyMessage { |
| "HTTP/1.0 200 OK\r\n" |
| "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n" |
| "Content-Length: " + QByteArray::number(text.size()) + "\r\n\r\n" |
| + text.toUtf8() |
| }; |
| socket->write(replyMessage); |
| } |
| }); |
| QOAuth2AuthorizationCodeFlow oauth2; |
| oauth2.setAuthorizationUrl(webServer.url(QLatin1String("authorization"))); |
| oauth2.setAccessTokenUrl(webServer.url(QLatin1String("accessToken"))); |
| ReplyHandler replyHandler; |
| oauth2.setReplyHandler(&replyHandler); |
| connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, [&](const QUrl &url) { |
| const QUrlQuery query(url.query()); |
| replyHandler.emitCallbackReceived(QVariantMap { |
| { QLatin1String("code"), QLatin1String("test") }, |
| { QLatin1String("state"), |
| query.queryItemValue(QLatin1String("state")) } |
| }); |
| }); |
| QSignalSpy grantedSpy(&oauth2, &QOAuth2AuthorizationCodeFlow::granted); |
| oauth2.grant(); |
| QTRY_COMPARE(grantedSpy.count(), 1); |
| QCOMPARE(oauth2.token(), QLatin1String("token")); |
| } |
| |
| void tst_OAuth2::refreshToken() |
| { |
| WebServer webServer([](const WebServer::HttpRequest &request, QTcpSocket *socket) { |
| if (request.url.path() == QLatin1String("/accessToken")) { |
| const QString text = "access_token=token&token_type=bearer"; |
| const QByteArray replyMessage { |
| "HTTP/1.0 200 OK\r\n" |
| "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n" |
| "Content-Length: " + QByteArray::number(text.size()) + "\r\n\r\n" |
| + text.toUtf8() |
| }; |
| socket->write(replyMessage); |
| } |
| }); |
| QOAuth2AuthorizationCodeFlow oauth2; |
| oauth2.setAccessTokenUrl(webServer.url(QLatin1String("accessToken"))); |
| ReplyHandler replyHandler; |
| oauth2.setReplyHandler(&replyHandler); |
| oauth2.setRefreshToken(QLatin1String("refresh_token")); |
| QSignalSpy grantedSpy(&oauth2, &QOAuth2AuthorizationCodeFlow::granted); |
| oauth2.refreshAccessToken(); |
| QTRY_COMPARE(grantedSpy.count(), 1); |
| QCOMPARE(oauth2.token(), QLatin1String("token")); |
| } |
| |
| void tst_OAuth2::getAndRefreshToken() |
| { |
| // In this test we use the grant_type as a token to be able to |
| // identify the token request from the token refresh. |
| WebServer webServer([](const WebServer::HttpRequest &request, QTcpSocket *socket) { |
| if (request.url.path() == QLatin1String("/accessToken")) { |
| const QUrlQuery query(request.body); |
| const QString format = QStringLiteral("access_token=%1&token_type=bearer&expires_in=1&" |
| "refresh_token=refresh_token"); |
| const auto text = format.arg(query.queryItemValue(QLatin1String("grant_type"))); |
| const QByteArray replyMessage { |
| "HTTP/1.0 200 OK\r\n" |
| "Content-Type: application/x-www-form-urlencoded; charset=\"utf-8\"\r\n" |
| "Content-Length: " + QByteArray::number(text.size()) + "\r\n\r\n" |
| + text.toUtf8() |
| }; |
| socket->write(replyMessage); |
| } |
| }); |
| QOAuth2AuthorizationCodeFlow oauth2; |
| oauth2.setAuthorizationUrl(webServer.url(QLatin1String("authorization"))); |
| oauth2.setAccessTokenUrl(webServer.url(QLatin1String("accessToken"))); |
| ReplyHandler replyHandler; |
| oauth2.setReplyHandler(&replyHandler); |
| connect(&oauth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, [&](const QUrl &url) { |
| const QUrlQuery query(url.query()); |
| replyHandler.emitCallbackReceived(QVariantMap { |
| { QLatin1String("code"), QLatin1String("test") }, |
| { QLatin1String("state"), |
| query.queryItemValue(QLatin1String("state")) } |
| }); |
| }); |
| QSignalSpy grantedSpy(&oauth2, &QOAuth2AuthorizationCodeFlow::granted); |
| oauth2.grant(); |
| QTRY_COMPARE(grantedSpy.count(), 1); |
| QCOMPARE(oauth2.token(), QLatin1String("authorization_code")); |
| grantedSpy.clear(); |
| oauth2.refreshAccessToken(); |
| QTRY_COMPARE(grantedSpy.count(), 1); |
| QCOMPARE(oauth2.token(), QLatin1String("refresh_token")); |
| } |
| |
| void tst_OAuth2::prepareRequest() |
| { |
| QOAuth2AuthorizationCodeFlow oauth2; |
| oauth2.setToken(QStringLiteral("access_token")); |
| |
| QNetworkRequest request(QUrl("http://localhost")); |
| oauth2.prepareRequest(&request, QByteArray()); |
| QCOMPARE(request.rawHeader("Authorization"), QByteArray("Bearer access_token")); |
| } |
| |
| QTEST_MAIN(tst_OAuth2) |
| #include "tst_oauth2.moc" |