Skip to content

Improve oauth2 authorization #9339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/libsync/configfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ const QString newBigFolderSizeLimitC() { return QStringLiteral("newBigFolderSize
const QString useNewBigFolderSizeLimitC() { return QStringLiteral("useNewBigFolderSizeLimit"); }
const QString confirmExternalStorageC() { return QStringLiteral("confirmExternalStorage"); }
const QString moveToTrashC() { return QStringLiteral("moveToTrash"); }
const QString oauthPromptC() { return QStringLiteral("oauthPrompt"); }
const QString oauthBasicAuthC() { return QStringLiteral("oauthBasicAuth"); }
}

QString ConfigFile::_confDir = QString();
Expand Down Expand Up @@ -752,6 +754,31 @@ void ConfigFile::setPromptDeleteFiles(bool promptDeleteFiles)
settings.setValue(promptDeleteC(), promptDeleteFiles);
}

bool ConfigFile::oauthPrompt() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(oauthPromptC(), true).toBool();
}

void ConfigFile::setOauthPrompt(bool oauthPrompt)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue(oauthPromptC(), oauthPrompt);
}

bool ConfigFile::oauthBasicAuth() const
{
QSettings settings(configFile(), QSettings::IniFormat);
return settings.value(oauthBasicAuthC(), true).toBool();
}

void ConfigFile::setOauthBasicAuth(bool oauthBasicAuth)
{
QSettings settings(configFile(), QSettings::IniFormat);
settings.setValue(oauthBasicAuthC(), oauthBasicAuth);
}


bool ConfigFile::monoIcons() const
{
QSettings settings(configFile(), QSettings::IniFormat);
Expand Down
8 changes: 8 additions & 0 deletions src/libsync/configfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,14 @@ class OWNCLOUDSYNC_EXPORT ConfigFile
bool confirmExternalStorage() const;
void setConfirmExternalStorage(bool);

//disable sending of the prompt parameter for the oauth2 authorization_endpoint
bool oauthPrompt() const;
void setOauthPrompt(bool);

//disable sending of basic auth header for the oauth2 token endpoint
bool oauthBasicAuth() const;
void setOauthBasicAuth(bool);

/** If we should move the files deleted on the server in the trash */
bool moveToTrash() const;
void setMoveToTrash(bool);
Expand Down
24 changes: 17 additions & 7 deletions src/libsync/creds/oauth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "creds/oauth.h"

#include "configfile.h"
#include "account.h"
#include "common/version.h"
#include "credentialmanager.h"
Expand Down Expand Up @@ -227,16 +228,18 @@ void OAuth::startAuthentication()
httpReplyAndClose(socket, QByteArrayLiteral("400 Bad Request"), QByteArrayLiteral("<html><head><title>400 Bad Request</title></head><body><center><h1>400 Bad Request</h1></center></body></html>"));
return;
}
// we only allow one response
qCDebug(lcOauth) << "Recieved the first valid request, stoping to listen";
_server.close();

auto job = postTokenRequest({
{ QStringLiteral("grant_type"), QStringLiteral("authorization_code") },
{ QStringLiteral("code"), args.queryItemValue(QStringLiteral("code")) },
{ QStringLiteral("redirect_uri"), QStringLiteral("%1:%2").arg(_redirectUrl, QString::number(_server.serverPort())) },
{ QStringLiteral("code_verifier"), QString::fromUtf8(_pkceCodeVerifier) },
});

// we only allow one response
qCDebug(lcOauth) << "Recieved the first valid request, stoping to listen";
_server.close();

QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, socket](QNetworkReply *reply) {
const auto jsonData = reply->readAll();
QJsonParseError jsonParseError;
Expand Down Expand Up @@ -403,11 +406,14 @@ void OAuth::finalize(const QPointer<QTcpSocket> &socket, const QString &accessTo

SimpleNetworkJob *OAuth::postTokenRequest(const QList<QPair<QString, QString>> &queryItems)
{
ConfigFile cfg;
const QUrl requestTokenUrl = _tokenEndpoint.isEmpty() ? Utility::concatUrlPath(_account->url(), QStringLiteral("/index.php/apps/oauth2/api/v1/token")) : _tokenEndpoint;
QNetworkRequest req;
const QByteArray basicAuth = QStringLiteral("%1:%2").arg(_clientId, _clientSecret).toUtf8().toBase64();
req.setRawHeader("Authorization", "Basic " + basicAuth);
req.setAttribute(HttpCredentials::DontAddCredentialsAttribute, true);
if (cfg.oauthBasicAuth()){
const QByteArray basicAuth = QStringLiteral("%1:%2").arg(_clientId, _clientSecret).toUtf8().toBase64();
req.setRawHeader("Authorization", "Basic " + basicAuth);
req.setAttribute(HttpCredentials::DontAddCredentialsAttribute, true);
}

QUrlQuery arguments;
arguments.setQueryItems(QList<QPair<QString, QString>> { { QStringLiteral("client_id"), _clientId },
Expand All @@ -431,6 +437,7 @@ QByteArray OAuth::generateRandomString(size_t size) const

QUrl OAuth::authorisationLink() const
{
ConfigFile cfg;
Q_ASSERT(_server.isListening());
QUrlQuery query;
const QByteArray code_challenge = QCryptographicHash::hash(_pkceCodeVerifier, QCryptographicHash::Sha256)
Expand All @@ -441,9 +448,12 @@ QUrl OAuth::authorisationLink() const
{ QStringLiteral("code_challenge"), QString::fromLatin1(code_challenge) },
{ QStringLiteral("code_challenge_method"), QStringLiteral("S256") },
{ QStringLiteral("scope"), Theme::instance()->openIdConnectScopes() },
{ QStringLiteral("prompt"), Theme::instance()->openIdConnectPrompt() },
{ QStringLiteral("state"), QString::fromUtf8(_state) } });

if (cfg.oauthPrompt()){
query.addQueryItem(QStringLiteral("prompt"), Theme::instance()->openIdConnectPrompt());
}

if (!_account->davUser().isNull()) {
const QString davUser = _account->davUser().replace(QLatin1Char('+'), QStringLiteral("%2B")); // Issue #7762;
// open id connect
Expand Down