#pragma once #include #include #include #include #include "Reply.h" #include "RequestParameter.h" #include "Bits.h" namespace Katabasis { class ReplyServer; class PollServer; /// Simple OAuth2 Device Flow authenticator. class DeviceFlow: public QObject { Q_OBJECT public: Q_ENUMS(GrantFlow) public: struct Options { QString userAgent = QStringLiteral("Katabasis/1.0"); QString responseType = QStringLiteral("code"); QString scope; QString clientIdentifier; QString clientSecret; QUrl authorizationUrl; QUrl accessTokenUrl; }; public: /// Are we authenticated? bool linked(); /// Authentication token. QString token(); /// Provider-specific extra tokens, available after a successful authentication QVariantMap extraTokens(); public: // TODO: put in `Options` /// User-defined extra parameters to append to request URL QVariantMap extraRequestParams(); void setExtraRequestParams(const QVariantMap &value); // TODO: split up the class into multiple, each implementing one OAuth2 flow /// Grant type (if non-standard) QString grantType(); void setGrantType(const QString &value); public: /// Constructor. /// @param parent Parent object. explicit DeviceFlow(Options & opts, Token & token, QObject *parent = 0, QNetworkAccessManager *manager = 0); /// Get refresh token. QString refreshToken(); /// Get token expiration time QDateTime expires(); public slots: /// Authenticate. void login(); /// De-authenticate. void logout(); /// Refresh token. bool refresh(); /// Handle situation where reply server has opted to close its connection void serverHasClosed(bool paramsfound = false); signals: /// Emitted when client needs to open a web browser window, with the given URL. void openBrowser(const QUrl &url); /// Emitted when client can close the browser window. void closeBrowser(); /// Emitted when client needs to show a verification uri and user code void showVerificationUriAndCode(const QUrl &uri, const QString &code, int expiresIn); /// Emitted when the internal state changes void activityChanged(Activity activity); public slots: /// Handle verification response. void onVerificationReceived(QMap); protected slots: /// Handle completion of a Device Authorization Request void onDeviceAuthReplyFinished(); /// Handle completion of a refresh request. void onRefreshFinished(); /// Handle failure of a refresh request. void onRefreshError(QNetworkReply::NetworkError error, QNetworkReply *reply); protected: /// Set refresh token. void setRefreshToken(const QString &v); /// Set token expiration time. void setExpires(QDateTime v); /// Start polling authorization server void startPollServer(const QVariantMap ¶ms, int expiresIn); /// Set authentication token. void setToken(const QString &v); /// Set the linked state void setLinked(bool v); /// Set extra tokens found in OAuth response void setExtraTokens(QVariantMap extraTokens); /// Set local poll server void setPollServer(PollServer *server); PollServer * pollServer() const; void updateActivity(Activity activity); protected: Options options_; QVariantMap extraReqParams_; QNetworkAccessManager *manager_ = nullptr; ReplyList timedReplies_; QString grantType_; protected: Token &token_; private: PollServer *pollServer_ = nullptr; Activity activity_ = Activity::Idle; }; }