File indexing completed on 2024-12-22 04:57:53

0001 /*
0002     SPDX-License-Identifier: BSD-2-Clause
0003 */
0004 
0005 #pragma once
0006 
0007 #include <QNetworkAccessManager>
0008 #include <QNetworkReply>
0009 #include <QUrl>
0010 
0011 #include "o2/o0baseauth.h"
0012 
0013 class O2ReplyServer;
0014 
0015 /// Simple OAuth 1.0 authenticator.
0016 class O1 : public O0BaseAuth
0017 {
0018     Q_OBJECT
0019 
0020 public:
0021     /// Signature method
0022     Q_PROPERTY(QString signatureMethod READ signatureMethod WRITE setSignatureMethod NOTIFY signatureMethodChanged)
0023     QString signatureMethod();
0024     void setSignatureMethod(const QString &value);
0025 
0026     /// Token request URL.
0027     Q_PROPERTY(QUrl requestTokenUrl READ requestTokenUrl WRITE setRequestTokenUrl NOTIFY requestTokenUrlChanged)
0028     QUrl requestTokenUrl() const;
0029     void setRequestTokenUrl(const QUrl &value);
0030 
0031     /// Parameters to pass with request URL.
0032     Q_PROPERTY(QList<O0RequestParameter> requestParameters READ requestParameters WRITE setRequestParameters)
0033     QList<O0RequestParameter> requestParameters();
0034     void setRequestParameters(const QList<O0RequestParameter> &value);
0035 
0036     /// Callback URL.
0037     /// It should contain a `%1` place marker, to be replaced by `O0BaseAuth::localPort()`.
0038     /// Defaults to `O2_CALLBACK_URL`.
0039     Q_PROPERTY(QString callbackUrl READ callbackUrl WRITE setCallbackUrl)
0040     QString callbackUrl() const;
0041     void setCallbackUrl(const QString &value);
0042 
0043     /// Authorization URL.
0044     Q_PROPERTY(QUrl authorizeUrl READ authorizeUrl WRITE setAuthorizeUrl NOTIFY authorizeUrlChanged)
0045     QUrl authorizeUrl() const;
0046     void setAuthorizeUrl(const QUrl &value);
0047 
0048     /// Access token URL.
0049     Q_PROPERTY(QUrl accessTokenUrl READ accessTokenUrl WRITE setAccessTokenUrl NOTIFY accessTokenUrlChanged)
0050     QUrl accessTokenUrl() const;
0051     void setAccessTokenUrl(const QUrl &value);
0052 
0053     /// Constructor.
0054     explicit O1(QObject *parent = nullptr);
0055 
0056     /// Parse a URL-encoded response string.
0057     static QMap<QString, QString> parseResponse(const QByteArray &response);
0058 
0059     /// Build the value of the "Authorization:" header.
0060     static QByteArray buildAuthorizationHeader(const QList<O0RequestParameter> &oauthParams);
0061 
0062     /// Create unique bytes to prevent replay attacks.
0063     static QByteArray nonce();
0064 
0065     /// Generate signature string depending on signature method type
0066     QByteArray generateSignature(const QList<O0RequestParameter> &headers,
0067                                  const QNetworkRequest &req,
0068                                  const QList<O0RequestParameter> &signingParameters,
0069                                  QNetworkAccessManager::Operation operation);
0070 
0071     /// Calculate the HMAC-SHA1 signature of a request.
0072     /// @param  oauthParams     OAuth parameters.
0073     /// @param  otherParams     Other parameters participating in signing.
0074     /// @param  URL             Request URL. May contain query parameters, but they will not be used for signing.
0075     /// @param  op              HTTP operation.
0076     /// @param  consumerSecret  Consumer (application) secret.
0077     /// @param  tokenSecret     Authorization token secret (empty if not yet available).
0078     /// @return Signature that can be used as the value of the "oauth_signature" parameter.
0079     static QByteArray sign(const QList<O0RequestParameter> &oauthParams,
0080                            const QList<O0RequestParameter> &otherParams,
0081                            const QUrl &url,
0082                            QNetworkAccessManager::Operation op,
0083                            const QString &consumerSecret,
0084                            const QString &tokenSecret);
0085 
0086     /// Build a base string for signing.
0087     static QByteArray getRequestBase(const QList<O0RequestParameter> &oauthParams,
0088                                      const QList<O0RequestParameter> &otherParams,
0089                                      const QUrl &url,
0090                                      QNetworkAccessManager::Operation op);
0091 
0092     /// Build a concatenated/percent-encoded string from a list of headers.
0093     static QByteArray encodeHeaders(const QList<O0RequestParameter> &headers);
0094 
0095 public Q_SLOTS:
0096     /// Authenticate.
0097     Q_INVOKABLE void link() override;
0098 
0099     /// De-authenticate.
0100     Q_INVOKABLE void unlink() override;
0101 
0102 Q_SIGNALS:
0103     void requestTokenUrlChanged();
0104     void authorizeUrlChanged();
0105     void accessTokenUrlChanged();
0106     void signatureMethodChanged();
0107 
0108 protected Q_SLOTS:
0109     /// Handle verification received from the reply server.
0110     virtual void onVerificationReceived(const QMultiMap<QString, QString> &params);
0111 
0112     /// Handle token request error.
0113     virtual void onTokenRequestError(QNetworkReply::NetworkError error);
0114 
0115     /// Handle token request finished.
0116     virtual void onTokenRequestFinished();
0117 
0118     /// Handle token exchange error.
0119     void onTokenExchangeError(QNetworkReply::NetworkError error);
0120 
0121     /// Handle token exchange finished.
0122     void onTokenExchangeFinished();
0123 
0124 protected:
0125     /// Exchange temporary token to authentication token
0126     void exchangeToken();
0127 
0128     QUrl requestUrl_;
0129     QList<O0RequestParameter> requestParameters_;
0130     QString callbackUrl_;
0131     QUrl tokenUrl_;
0132     QUrl refreshTokenUrl_;
0133     QString verifier_;
0134     QString signatureMethod_;
0135     QNetworkAccessManager *manager_ = nullptr;
0136     O2ReplyServer *replyServer_ = nullptr;
0137 };