File indexing completed on 2026-05-17 12:33:23
0001 /* 0002 SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "githubauthenticationjob.h" 0008 #include "githubauthenticationplugin_debug.h" 0009 #include "githubauthenticationsettings.h" 0010 #include <QDesktopServices> 0011 #include <QOAuth2AuthorizationCodeFlow> 0012 #include <QOAuthHttpServerReplyHandler> 0013 #include <QTimer> 0014 0015 GitHubAuthenticationJob::GitHubAuthenticationJob(QObject *parent) 0016 : QObject{parent} 0017 , mOAuth2(new QOAuth2AuthorizationCodeFlow(this)) 0018 { 0019 } 0020 0021 GitHubAuthenticationJob::~GitHubAuthenticationJob() = default; 0022 0023 void GitHubAuthenticationJob::doRequest() 0024 { 0025 // TODO 0026 0027 deleteLater(); 0028 } 0029 0030 GitHubAuthenticationJob::GitHubInfo GitHubAuthenticationJob::gitHubInfo() const 0031 { 0032 return mGitHubInfo; 0033 } 0034 0035 void GitHubAuthenticationJob::setGitHubInfo(const GitHubInfo &newGitHubInfo) 0036 { 0037 mGitHubInfo = newGitHubInfo; 0038 } 0039 0040 void GitHubAuthenticationJob::start() 0041 { 0042 if (!mGitHubInfo.isValid()) { 0043 qCWarning(RUQOLA_GITHUBAUTHENTICATION_PLUGIN_LOG) << "Lab info is invalid"; 0044 deleteLater(); 0045 return; 0046 } 0047 #if 0 0048 QString clientId = "CLIENT ID FROM API CREDENTIALS"; 0049 QString authUri = "https://accounts.google.com/o/oauth2/auth"; 0050 QString tokenUri = "https://accounts.google.com/o/oauth2/token"; 0051 QStringList redirectUris; 0052 redirectUris << "http://127.0.0.1:54321/"; //ensure this is included in the API credentials under authorized URI 0053 QString redirectUri = redirectUris[0]; 0054 QString clientSecret = "YOUR CLIENT SECRET FROM API CREDENTIALS"; 0055 auto google = new QOAuth2AuthorizationCodeFlow(this); 0056 google->setScope("email"); 0057 google->setAuthorizationUrl(authUri); 0058 google->setClientIdentifier(clientId); 0059 google->setAccessTokenUrl(tokenUri); 0060 google->setClientIdentifierSharedKey(clientSecret); 0061 0062 // Use the same port number as above 0063 auto replyHandler = new QOAuthHttpServerReplyHandler(54321, this); 0064 google->setReplyHandler(replyHandler); 0065 0066 // Set up the function to modify AND REPLACE the parameters 0067 google->setModifyParametersFunction([](QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* parameters) { 0068 if (stage == QAbstractOAuth::Stage::RequestingAccessToken) { 0069 auto encodedCode = parameters->value("code").toByteArray(); 0070 parameters->replace("code", QUrl::fromPercentEncoding(encodedCode)); 0071 } 0072 }); 0073 0074 // Connect the signals to retrieve the tokens, if you want to see them 0075 connect(google, &QOAuth2AuthorizationCodeFlow::tokenChanged, [=](const QString &token) 0076 { 0077 qDebug() << "Token changed:" << token; 0078 0079 }); 0080 connect(replyHandler, &QOAuthHttpServerReplyHandler::tokensReceived, [](const QVariantMap &tokens) 0081 { 0082 qDebug() << "Tokens received:" << tokens; 0083 }); 0084 0085 connect(google, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl); 0086 0087 // Once you are granted access, make a request via the Google API 0088 connect(google, &QOAuth2AuthorizationCodeFlow::granted, [=] 0089 { 0090 qDebug() << "in the granted block now"; 0091 // This block is run once you have logged into the browser successfully 0092 0093 auto rep = google->get(QUrl("https://www.googleapis.com/oauth2/v1/userinfo?alt=json")); 0094 QEventLoop loop; 0095 connect(rep, &QNetworkReply::finished, &loop, &QEventLoop::quit); 0096 loop.exec(); 0097 QString currentByteArray = rep->readAll(); 0098 qDebug() << "network reply google api connect step get info" << currentByteArray; 0099 0100 }); 0101 0102 google->grant(); 0103 0104 0 0105 0106 #endif 0107 0108 auto replyHandler = new QOAuthHttpServerReplyHandler(11450, mOAuth2); 0109 mOAuth2->setClientIdentifier(mGitHubInfo.clientId); 0110 mOAuth2->setReplyHandler(replyHandler); 0111 mOAuth2->setAuthorizationUrl(GitHubAuthenticationSettings::authorizeUrl()); 0112 mOAuth2->setAccessTokenUrl(GitHubAuthenticationSettings::accessTokenUrl()); 0113 mOAuth2->setScope(QStringLiteral("openid")); 0114 mOAuth2->setToken(mGitHubInfo.token); 0115 mOAuth2->setRefreshToken(mGitHubInfo.refreshToken); 0116 0117 QObject::connect(mOAuth2, &QOAuth2AuthorizationCodeFlow::statusChanged, [this](QAbstractOAuth::Status status) { 0118 qCDebug(RUQOLA_GITHUBAUTHENTICATION_PLUGIN_LOG) 0119 << (int)status << mOAuth2->token() << mOAuth2->refreshToken() << mOAuth2->expirationAt() << mOAuth2->extraTokens(); 0120 if (status == QAbstractOAuth::Status::Granted) { 0121 // TODO store info in qtkeychain 0122 qCDebug(RUQOLA_GITHUBAUTHENTICATION_PLUGIN_LOG) << "authorization granted"; 0123 doRequest(); 0124 QTimer::singleShot(std::max<qint64>(5 * 60 * 1000, QDateTime::currentDateTime().secsTo(mOAuth2->expirationAt()) * 800), 0125 mOAuth2, 0126 &QOAuth2AuthorizationCodeFlow::refreshAccessToken); 0127 } 0128 }); 0129 QObject::connect(mOAuth2, &QOAuth2AuthorizationCodeFlow::authorizationCallbackReceived, [](const QVariantMap &m) { 0130 qCDebug(RUQOLA_GITHUBAUTHENTICATION_PLUGIN_LOG) << "auth callback received" << m; 0131 }); 0132 QObject::connect(mOAuth2, &QOAuth2AuthorizationCodeFlow::error, [](const QString &err, const QString &desc) { 0133 qCDebug(RUQOLA_GITHUBAUTHENTICATION_PLUGIN_LOG) << "error" << err << desc; 0134 }); 0135 QObject::connect(mOAuth2, &QOAuth2AuthorizationCodeFlow::authorizeWithBrowser, &QDesktopServices::openUrl); 0136 0137 if (mOAuth2->refreshToken().isEmpty()) { 0138 mOAuth2->grant(); 0139 } else if (!mOAuth2->expirationAt().isValid() || mOAuth2->expirationAt() < QDateTime::currentDateTimeUtc()) { 0140 mOAuth2->refreshAccessToken(); 0141 } 0142 } 0143 0144 bool GitHubAuthenticationJob::GitHubInfo::isValid() const 0145 { 0146 return !url.isEmpty() && !clientId.isEmpty(); 0147 } 0148 0149 #include "moc_githubauthenticationjob.cpp"