QOAuth2DeviceAuthorizationFlow Class
The QOAuth2DeviceAuthorizationFlow class provides an implementation of the Device Authorization Grant flow. More...
Header: | #include <QOAuth2DeviceAuthorizationFlow> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS NetworkAuth) target_link_libraries(mytarget PRIVATE Qt6::NetworkAuth) |
qmake: | QT += networkauth |
Since: | Qt 6.9 |
Inherits: | QAbstractOAuth2 |
Properties
|
|
Public Functions
QOAuth2DeviceAuthorizationFlow() | |
QOAuth2DeviceAuthorizationFlow(QObject *parent) | |
QOAuth2DeviceAuthorizationFlow(QNetworkAccessManager *manager, QObject *parent = nullptr) | |
virtual | ~QOAuth2DeviceAuthorizationFlow() override |
QUrl | completeVerificationUrl() const |
bool | isPolling() const |
void | setTokenUrl(const QUrl &tokenUrl) |
QUrl | tokenUrl() const |
QString | userCode() const |
QDateTime | userCodeExpirationAt() const |
QUrl | verificationUrl() const |
Public Slots
virtual void | grant() override |
void | refreshAccessToken() |
bool | startTokenPolling() |
void | stopTokenPolling() |
Signals
void | authorizeWithUserCode(const QUrl &verificationUrl, const QString &userCode, const QUrl &completeVerificationUrl) |
void | completeVerificationUrlChanged(const QUrl &completeVerificationUrl) |
void | isPollingChanged(bool isPolling) |
void | tokenUrlChanged(const QUrl &tokenUrl) |
void | userCodeChanged(const QString &userCode) |
void | userCodeExpirationAtChanged(const QDateTime &expiration) |
void | verificationUrlChanged(const QUrl &verificationUrl) |
Detailed Description
This class implements the Device Authorization Grant flow, which is used to obtain and refresh access tokens and ID tokens, particularly on devices lacking a user-agent or with limited input capabilities. These devices include televisions, machine HMIs, appliances, and IoT devices.
Device flow can be used on any platform and operating system that is capable of SSL/TLS requests. Unlike QOAuth2AuthorizationCodeFlow, this flow is not based on redirects, and therefore does not use a reply handler.
Device Flow Usage
The following snippets illustrate the typical usage. First, we set up the flow similarly to QOAuth2AuthorizationCodeFlow:
m_deviceFlow.setAuthorizationUrl(QUrl(authorizationUrl)); m_deviceFlow.setTokenUrl(QUrl(accessTokenUrl)); m_deviceFlow.setRequestedScope({scope}); m_deviceFlow.setClientIdentifier(clientIdentifier); // The need for a client secret depends on the authorization server m_deviceFlow.setClientIdentifierSharedKey(clientSecret);
Then we connect to authorizeWithUserCode signal to handle the user authorization:
connect(&m_deviceFlow, &QOAuth2DeviceAuthorizationFlow::authorizeWithUserCode, this, [](const QUrl &verificationUrl, const QString &userCode, const QUrl &completeVerificationUrl) { if (completeVerificationUrl.isValid()) { // If the authorization server provided a complete URL // that already contains the necessary data as part of the URL parameters, // you can choose to use that qDebug() << "Complete verification uri:" << completeVerificationUrl; } else { // Authorization server provided only verification URL; use that qDebug() << "Verification uri and usercode:" << verificationUrl << userCode; } } );
This part is crucial to the flow, and how you handle it depends on your specific use case. One way or another, the user needs to complete the authorization.
Device flow does not define how this authorization completion is done, making it versatile for different use cases. This can be achieved by displaying the verification URI and user code to the user, who can then navigate to it on another device. Alternatively, you could present a QR code for the user to scan with their mobile device, send to a companion application, email to the user, and so on.
While authorization is pending, QOAuth2DeviceAuthorizationFlow polls the server at specific intervals (typically 5 seconds) until the user accepts or rejects the authorization, upon which the server responds accordingly and the flow concludes.
Errors can be detected as follows:
connect(&m_deviceFlow, &QAbstractOAuth::requestFailed, this, [](QAbstractOAuth::Error error) { Q_UNUSED(error); // Handle error }); connect(&m_deviceFlow, &QAbstractOAuth2::serverReportedErrorOccurred, this, [](const QString &error, const QString &errorDescription, const QUrl &uri) { // Check server reported error details if needed Q_UNUSED(error); Q_UNUSED(errorDescription); Q_UNUSED(uri); } );
QAbstractOAuth2::serverReportedErrorOccurred() signal can be used to get information on specific RFC-defined errors. However, unlike QAbstractOAuth::requestFailed(), it doesn't cover errors such as network errors or client configuration errors.
Flow completion is detected similarly as with QOAuth2AuthorizationCodeFlow, for example:
connect(&m_deviceFlow, &QAbstractOAuth::granted, this, [this](){ // Here we use QNetworkRequestFactory to store the access token m_api.setBearerToken(m_deviceFlow.token().toLatin1()); }); m_deviceFlow.grant();
Property Documentation
[read-only]
completeVerificationUrl : const QUrl
This property holds an URL for user to complete the authorization. The URL itself contains the user_code
and thus avoids the need for user to enter the code manually. Support for this complete URL varies between authorization servers.
Access functions:
QUrl | completeVerificationUrl() const |
Notifier signal:
void | completeVerificationUrlChanged(const QUrl &completeVerificationUrl) |
See also verificationUrl and Device Flow Usage.
[read-only]
isPolling : const bool
This property holds whether or not the flow is actively polling for tokens.
Access functions:
bool | isPolling() const |
Notifier signal:
void | isPollingChanged(bool isPolling) |
See also startTokenPolling() and stopTokenPolling().
tokenUrl : QUrl
This property holds the token endpoint URL that is used in token polling.
Access functions:
QUrl | tokenUrl() const |
void | setTokenUrl(const QUrl &tokenUrl) |
Notifier signal:
void | tokenUrlChanged(const QUrl &tokenUrl) |
[read-only]
userCode : const QString
This property holds the user_code received in authorization response. This code is used by the user to complete the authorization.
Access functions:
QString | userCode() const |
Notifier signal:
void | userCodeChanged(const QString &userCode) |
See also verificationUrl, completeVerificationUrl, and Device Flow Usage.
[read-only]
userCodeExpirationAt : const QDateTime
This property holds the local time the user code and underlying device codes expire. The codes are typically valid between 5 and 30 minutes.
Access functions:
QDateTime | userCodeExpirationAt() const |
Notifier signal:
void | userCodeExpirationAtChanged(const QDateTime &expiration) |
See also userCode.
[read-only]
verificationUrl : const QUrl
This property holds the URL where user should enter the user code to complete authorization.
Access functions:
QUrl | verificationUrl() const |
Notifier signal:
void | verificationUrlChanged(const QUrl &verificationUrl) |
See also userCode, completeVerificationUrl, and Device Flow Usage.
Member Function Documentation
QOAuth2DeviceAuthorizationFlow::QOAuth2DeviceAuthorizationFlow()
Constructs a QOAuth2DeviceAuthorizationFlow object.
[explicit]
QOAuth2DeviceAuthorizationFlow::QOAuth2DeviceAuthorizationFlow(QObject *parent)
Constructs a QOAuth2DeviceAuthorizationFlow object with parent object parent.
[explicit]
QOAuth2DeviceAuthorizationFlow::QOAuth2DeviceAuthorizationFlow(QNetworkAccessManager *manager, QObject *parent = nullptr)
Constructs a QOAuth2DeviceAuthorizationFlow object using parent as parent and sets manager as the network access manager.
[override virtual noexcept]
QOAuth2DeviceAuthorizationFlow::~QOAuth2DeviceAuthorizationFlow()
Destroys the QOAuth2DeviceAuthorizationFlow instance.
[signal]
void QOAuth2DeviceAuthorizationFlow::authorizeWithUserCode(const QUrl &verificationUrl, const QString &userCode, const QUrl &completeVerificationUrl)
This signal is emitted when user should complete the authorization.
If authorization server has provided completeVerificationUrl, user can navigate to that URL. The URL contains the needed userCode and any other needed parameters.
Alternatively, the user needs to navigate to verificationUrl and enter userCode manually.
See also Device Flow Usage.
[override virtual slot]
void QOAuth2DeviceAuthorizationFlow::grant()
Reimplements: QAbstractOAuth::grant().
Starts the authorization flow as described in Device Grant RFC.
The flow consists of following steps:
- Authorization request to the authorization server
- User authorizing the access, see authorizeWithUserCode()
- Polling the authorization server until user has accepted or rejected the authorization (or codes expire)
- Indicating the result to the application (see granted() and QAbstractOAuth::requestFailed())
The flow progresses automatically from authorization to token polling.
Calling this function will reset any previous authorization data.
See also authorizeWithUserCode(), granted(), QAbstractOAuth::requestFailed(), isPolling, startTokenPolling(), stopTokenPolling(), and Device Flow Usage.
[slot]
void QOAuth2DeviceAuthorizationFlow::refreshAccessToken()
Call this function to refresh the tokens.
If the refresh request was initiated successfully, the status is set to QAbstractOAuth::Status::RefreshingToken; otherwise the requestFailed() signal is emitted and the status is not changed. Tokens cannot be refreshed while isPolling is true
.
This function has no effect if the token refresh process is already in progress.
If refreshing the token fails and an access token exists, the status is set to QAbstractOAuth::Status::Granted, and to QAbstractOAuth::Status::NotAuthenticated if an access token does not exist.
See also QAbstractOAuth::requestFailed().
[slot]
bool QOAuth2DeviceAuthorizationFlow::startTokenPolling()
Starts token polling. Returns true
if the start was successful (or was already active), and false
otherwise.
Calling this function is not necessary in a typical use case. Once the authorization request has completed, as a result of grant() call, the polling is started automatically.
This function can be useful in cases where resuming (retrying) the token polling a bit later is needed, without restarting the whole authorization flow. For example in case of a transient network connectivity loss.
Polling interval is defined by the authorization server, and is typically 5 seconds. First poll request is sent once the first interval has elapsed.
See also isPolling, stopTokenPolling(), and Device Flow Usage.
[slot]
void QOAuth2DeviceAuthorizationFlow::stopTokenPolling()
Stops token polling. Any potential outstanding poll requests are silently discarded.
See also isPolling and startTokenPolling().
© 2024 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.