diff options
Diffstat (limited to 'src/oauth/qoauth2authorizationcodeflow.cpp')
| -rw-r--r-- | src/oauth/qoauth2authorizationcodeflow.cpp | 32 |
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)); |
