diff options
author | Michael Schuster <michael@schuster.ms> | 2019-08-24 17:21:44 +0300 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2019-08-26 21:03:15 +0300 |
commit | fd8345ccbe623ebee624477d2abe002bad181298 (patch) | |
tree | 11bf5047899a43c7efe8669dc3ef253101c0122a /src/gui/creds | |
parent | 7add98e9a316e42a28e55a5296fef30f557d2461 (diff) |
Login Flow V2: adds re-auth upon logout, improvements
- Implements re-auth upon logout -> login
- Improves UI and security
TODO:
- SSL: Client certificate login is possible at the first time only but missing after relaunch
Signed-off-by: Michael Schuster <michael@schuster.ms>
Diffstat (limited to 'src/gui/creds')
-rw-r--r-- | src/gui/creds/flow2auth.cpp | 38 | ||||
-rw-r--r-- | src/gui/creds/flow2auth.h | 5 | ||||
-rw-r--r-- | src/gui/creds/webflowcredentials.cpp | 25 | ||||
-rw-r--r-- | src/gui/creds/webflowcredentialsdialog.cpp | 49 | ||||
-rw-r--r-- | src/gui/creds/webflowcredentialsdialog.h | 13 |
5 files changed, 94 insertions, 36 deletions
diff --git a/src/gui/creds/flow2auth.cpp b/src/gui/creds/flow2auth.cpp index 76ff7c4ac..e570e01d4 100644 --- a/src/gui/creds/flow2auth.cpp +++ b/src/gui/creds/flow2auth.cpp @@ -34,9 +34,9 @@ Flow2Auth::~Flow2Auth() void Flow2Auth::start() { - // Note: All startup code is in openBrowser() to allow reinitiate a new request with - // fresh tokens. Opening the same pollEndpoint link twice triggers an expiration - // message by the server (security, intended design). + // Note: All startup code is in openBrowser() to allow reinitiate a new request with + // fresh tokens. Opening the same pollEndpoint link twice triggers an expiration + // message by the server (security, intended design). openBrowser(); } @@ -91,6 +91,7 @@ void Flow2Auth::openBrowser() _pollEndpoint = pollEndpoint; + // Start polling ConfigFile cfg; std::chrono::milliseconds polltime = cfg.remotePollInterval(); qCInfo(lcFlow2auth) << "setting remote poll timer interval to" << polltime.count() << "msec"; @@ -99,10 +100,10 @@ void Flow2Auth::openBrowser() _pollTimer.start(); - if (!QDesktopServices::openUrl(authorisationLink())) { - // TODO: Ask the user to copy and open the link instead of failing here! - - // We cannot open the browser, then we claim we don't support OAuth. + // Try to open Browser + if (!QDesktopServices::openUrl(authorisationLink())) { + // We cannot open the browser, then we claim we don't support Flow2Auth. + // Our UI callee should ask the user to copy and open the link. emit result(NotSupported, QString()); } }); @@ -110,7 +111,7 @@ void Flow2Auth::openBrowser() void Flow2Auth::slotPollTimerTimeout() { - _pollTimer.stop(); + _pollTimer.stop(); // Step 2: Poll QNetworkRequest req; @@ -122,6 +123,7 @@ void Flow2Auth::slotPollTimerTimeout() auto job = _account->sendRequest("POST", _pollEndpoint, req, requestBody); job->setTimeout(qMin(30 * 1000ll, job->timeoutMsec())); + QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) { auto jsonData = reply->readAll(); QJsonParseError jsonParseError; @@ -149,15 +151,25 @@ void Flow2Auth::slotPollTimerTimeout() } qCDebug(lcFlow2auth) << "Error when polling for the appPassword" << json << errorReason; - _pollTimer.start(); + // Forget sensitive data + appPassword.clear(); + loginName.clear(); + + // Failed: poll again + _pollTimer.start(); return; } - qCInfo(lcFlow2auth) << "Success getting the appPassword for user: " << loginName << " on server: " << serverUrl; - - _account->setUrl(serverUrl); + // Success + qCInfo(lcFlow2auth) << "Success getting the appPassword for user: " << loginName << ", server: " << serverUrl.toString(); + + _account->setUrl(serverUrl); + + emit result(LoggedIn, loginName, appPassword); - emit result(LoggedIn, loginName, appPassword); + // Forget sensitive data + appPassword.clear(); + loginName.clear(); }); } diff --git a/src/gui/creds/flow2auth.h b/src/gui/creds/flow2auth.h index 188865a0d..b53834a11 100644 --- a/src/gui/creds/flow2auth.h +++ b/src/gui/creds/flow2auth.h @@ -49,10 +49,9 @@ public: signals: /** * The state has changed. - * when logged in, token has the value of the token. + * when logged in, appPassword has the value of the app password. */ - // TODO: Remove refreshToken - void result(Flow2Auth::Result result, const QString &user = QString(), const QString &token = QString(), const QString &refreshToken = QString()); + void result(Flow2Auth::Result result, const QString &user = QString(), const QString &appPassword = QString()); private slots: void slotPollTimerTimeout(); diff --git a/src/gui/creds/webflowcredentials.cpp b/src/gui/creds/webflowcredentials.cpp index 70a709470..ecc0e61d9 100644 --- a/src/gui/creds/webflowcredentials.cpp +++ b/src/gui/creds/webflowcredentials.cpp @@ -114,12 +114,17 @@ void WebFlowCredentials::fetchFromKeychain() { } void WebFlowCredentials::askFromUser() { - _askDialog = new WebFlowCredentialsDialog(); + // LoginFlowV2 > WebViewFlow > OAuth > Shib > Basic + bool useFlow2 = (_account->serverVersionInt() >= Account::makeServerVersion(16, 0, 0)); - QUrl url = _account->url(); - QString path = url.path() + "/index.php/login/flow"; - url.setPath(path); - _askDialog->setUrl(url); + _askDialog = new WebFlowCredentialsDialog(_account, useFlow2); + + if (!useFlow2) { + QUrl url = _account->url(); + QString path = url.path() + "/index.php/login/flow"; + url.setPath(path); + _askDialog->setUrl(url); + } QString msg = tr("You have been logged out of %1 as user %2. Please login again") .arg(_account->displayName(), _user); @@ -142,10 +147,12 @@ void WebFlowCredentials::slotAskFromUserCredentialsProvided(const QString &user, .arg(_user); _askDialog->setError(msg); - QUrl url = _account->url(); - QString path = url.path() + "/index.php/login/flow"; - url.setPath(path); - _askDialog->setUrl(url); + if (!_askDialog->isUsingFlow2()) { + QUrl url = _account->url(); + QString path = url.path() + "/index.php/login/flow"; + url.setPath(path); + _askDialog->setUrl(url); + } return; } diff --git a/src/gui/creds/webflowcredentialsdialog.cpp b/src/gui/creds/webflowcredentialsdialog.cpp index 2d22ba06e..30a327afa 100644 --- a/src/gui/creds/webflowcredentialsdialog.cpp +++ b/src/gui/creds/webflowcredentialsdialog.cpp @@ -3,13 +3,21 @@ #include <QVBoxLayout> #include <QLabel> +#include "theme.h" +#include "wizard/owncloudwizardcommon.h" #include "wizard/webview.h" +#include "wizard/flow2authwidget.h" namespace OCC { -WebFlowCredentialsDialog::WebFlowCredentialsDialog(QWidget *parent) - : QDialog(parent) +WebFlowCredentialsDialog::WebFlowCredentialsDialog(Account *account, bool useFlow2, QWidget *parent) + : QDialog(parent), + _useFlow2(useFlow2), + _flow2AuthWidget(nullptr), + _webView(nullptr) { + setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); + _layout = new QVBoxLayout(this); //QString msg = tr("You have been logged out of %1 as user %2, please login again") @@ -17,28 +25,44 @@ WebFlowCredentialsDialog::WebFlowCredentialsDialog(QWidget *parent) _infoLabel = new QLabel(); _layout->addWidget(_infoLabel); - _webView = new WebView(); - _layout->addWidget(_webView); + if (_useFlow2) { + _flow2AuthWidget = new Flow2AuthWidget(account); + _layout->addWidget(_flow2AuthWidget); + + connect(_flow2AuthWidget, &Flow2AuthWidget::urlCatched, this, &WebFlowCredentialsDialog::urlCatched); + } else { + _webView = new WebView(); + _layout->addWidget(_webView); + + connect(_webView, &WebView::urlCatched, this, &WebFlowCredentialsDialog::urlCatched); + } _errorLabel = new QLabel(); _errorLabel->hide(); _layout->addWidget(_errorLabel); - setLayout(_layout); + Theme *theme = Theme::instance(); + WizardCommon::initErrorLabel(_errorLabel); - connect(_webView, &WebView::urlCatched, this, &WebFlowCredentialsDialog::urlCatched); + setLayout(_layout); } void WebFlowCredentialsDialog::closeEvent(QCloseEvent* e) { Q_UNUSED(e); - // Force calling WebView::~WebView() earlier so that _profile and _page are - // deleted in the correct order. - delete _webView; + if (_webView) { + // Force calling WebView::~WebView() earlier so that _profile and _page are + // deleted in the correct order. + delete _webView; + } + + if (_flow2AuthWidget) + delete _flow2AuthWidget; } void WebFlowCredentialsDialog::setUrl(const QUrl &url) { - _webView->setUrl(url); + if (_webView) + _webView->setUrl(url); } void WebFlowCredentialsDialog::setInfo(const QString &msg) { @@ -46,6 +70,11 @@ void WebFlowCredentialsDialog::setInfo(const QString &msg) { } void WebFlowCredentialsDialog::setError(const QString &error) { + if (_useFlow2 && _flow2AuthWidget) { + _flow2AuthWidget->setError(error); + return; + } + if (error.isEmpty()) { _errorLabel->hide(); } else { diff --git a/src/gui/creds/webflowcredentialsdialog.h b/src/gui/creds/webflowcredentialsdialog.h index 9849ee3a4..4e1f21c0d 100644 --- a/src/gui/creds/webflowcredentialsdialog.h +++ b/src/gui/creds/webflowcredentialsdialog.h @@ -4,23 +4,30 @@ #include <QDialog> #include <QUrl> +#include "accountfwd.h" + class QLabel; class QVBoxLayout; namespace OCC { class WebView; +class Flow2AuthWidget; class WebFlowCredentialsDialog : public QDialog { Q_OBJECT public: - WebFlowCredentialsDialog(QWidget *parent = nullptr); + WebFlowCredentialsDialog(Account *account, bool useFlow2, QWidget *parent = nullptr); void setUrl(const QUrl &url); void setInfo(const QString &msg); void setError(const QString &error); + const bool isUsingFlow2() const { + return _useFlow2; + } + protected: void closeEvent(QCloseEvent * e) override; @@ -28,7 +35,11 @@ signals: void urlCatched(const QString user, const QString pass, const QString host); private: + bool _useFlow2; + + Flow2AuthWidget *_flow2AuthWidget; WebView *_webView; + QLabel *_errorLabel; QLabel *_infoLabel; QVBoxLayout *_layout; |