summaryrefslogtreecommitdiffstats
path: root/src/oauth/qoauth2authorizationcodeflow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/oauth/qoauth2authorizationcodeflow.cpp')
-rw-r--r--src/oauth/qoauth2authorizationcodeflow.cpp32
1 files changed, 29 insertions, 3 deletions
diff --git a/src/oauth/qoauth2authorizationcodeflow.cpp b/src/oauth/qoauth2authorizationcodeflow.cpp
index 9eaef67..d979aae 100644
--- a/src/oauth/qoauth2authorizationcodeflow.cpp
+++ b/src/oauth/qoauth2authorizationcodeflow.cpp
@@ -55,6 +55,23 @@ QOAuth2AuthorizationCodeFlowPrivate::QOAuth2AuthorizationCodeFlowPrivate(
responseType = QStringLiteral("code");
}
+static QString toUrlFormEncoding(const QString &source)
+{
+ // RFC 6749 Appendix B
+ // https://datatracker.ietf.org/doc/html/rfc6749#appendix-B
+ // Replace spaces with plus, while percent-encoding the rest
+ QByteArray encoded = source.toUtf8().toPercentEncoding(" ");
+ encoded.replace(" ", "+");
+ return QString::fromUtf8(encoded);
+}
+
+static QString fromUrlFormEncoding(const QString &source)
+{
+ QByteArray decoded = source.toUtf8();
+ decoded = QByteArray::fromPercentEncoding(decoded.replace("+"," "));
+ return QString::fromUtf8(decoded);
+}
+
void QOAuth2AuthorizationCodeFlowPrivate::_q_handleCallback(const QVariantMap &data)
{
Q_Q(QOAuth2AuthorizationCodeFlow);
@@ -69,7 +86,8 @@ void QOAuth2AuthorizationCodeFlowPrivate::_q_handleCallback(const QVariantMap &d
const QString error = data.value(Key::error).toString();
const QString code = data.value(Key::code).toString();
- const QString receivedState = data.value(Key::state).toString();
+ const QString receivedState = fromUrlFormEncoding(data.value(Key::state).toString());
+
if (error.size()) {
const QString uri = data.value(Key::errorUri).toString();
const QString description = data.value(Key::errorDescription).toString();
@@ -118,13 +136,21 @@ void QOAuth2AuthorizationCodeFlowPrivate::_q_accessTokenRequestFinished(const QV
expiresIn = -1;
if (values.value(Key::refreshToken).isValid())
q->setRefreshToken(values.value(Key::refreshToken).toString());
- scope = values.value(Key::scope).toString();
+
if (accessToken.isEmpty()) {
qCWarning(loggingCategory, "Access token not received");
return;
}
q->setToken(accessToken);
+ // RFC 6749 section 5.1 https://datatracker.ietf.org/doc/html/rfc6749#section-5.1
+ // If the requested scope and granted scopes differ, server is REQUIRED to return
+ // the scope. If OTOH the scopes match, the server MAY omit the scope in the response,
+ // in which case we assume that the granted scope matches the requested scope.
+ const QString scope = values.value(Key::scope).toString();
+ if (!scope.isEmpty())
+ q->setScope(scope);
+
const QDateTime currentDateTime = QDateTime::currentDateTime();
if (expiresIn > 0 && currentDateTime.secsTo(expiresAt) != expiresIn) {
expiresAt = currentDateTime.addSecs(expiresIn);
@@ -350,7 +376,7 @@ QUrl QOAuth2AuthorizationCodeFlow::buildAuthenticateUrl(const QMultiMap<QString,
p.insert(Key::clientIdentifier, d->clientIdentifier);
p.insert(Key::redirectUri, callback());
p.insert(Key::scope, d->scope);
- p.insert(Key::state, state);
+ p.insert(Key::state, toUrlFormEncoding(state));
if (d->modifyParametersFunction)
d->modifyParametersFunction(Stage::RequestingAuthorization, &p);
url.setQuery(d->createQuery(p));