From 31df339565c09bfcbc56d3e4164cd3e51d4d7a30 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 9 Oct 2014 16:53:22 -0700 Subject: [PATCH] pipe username signature requirement through to DomainHandler --- .../resources/describe-settings.json | 2 +- domain-server/resources/web/js/settings.js | 8 +- interface/src/Application.cpp | 8 - interface/src/DatagramProcessor.cpp | 16 +- interface/src/ui/OAuthWebViewHandler.cpp | 168 ------------------ interface/src/ui/OAuthWebViewHandler.h | 43 ----- libraries/networking/src/DomainHandler.cpp | 2 + libraries/networking/src/DomainHandler.h | 4 + 8 files changed, 17 insertions(+), 234 deletions(-) delete mode 100644 interface/src/ui/OAuthWebViewHandler.cpp delete mode 100644 interface/src/ui/OAuthWebViewHandler.h diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 3f4e69a061..74db2c1e52 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -64,7 +64,7 @@ "name": "allowed_users", "type": "table", "label": "Allowed Users", - "help": "A list of usernames for the High Fidelity users you want to allow into your domain.
If the list is blank, all users are allowed to connect.
You are always allowed to connect to your domain directly from your local machine.", + "help": "List the High Fidelity names for people you want to be able to connect to this domain.
An empty list means everyone.
You can always connect from this machine.", "numbered": false, "columns": [ { diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index ccc254dbc3..56e451abf6 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -276,13 +276,15 @@ function makeTable(setting, setting_name, setting_value) { html += "" if (isArray) { - colIsArray = _.isArray(row) - colValue = colIsArray ? row : row[col.name] + rowIsObject = setting.columns.length > 1 + colValue = rowIsObject ? row[col.name] : row html += colValue // for arrays we add a hidden input to this td so that values can be posted appropriately html += "" + + (rowIsObject ? "." + col.name : "") + "' value='" + colValue + "'/>" + + console.log(html) } else if (row.hasOwnProperty(col.name)) { html += row[col.name] } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 718360864a..da5c858fff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -90,7 +90,6 @@ #include "scripting/WindowScriptingInterface.h" #include "ui/InfoView.h" -#include "ui/OAuthWebViewHandler.h" #include "ui/Snapshot.h" #include "ui/Stats.h" #include "ui/TextRenderer.h" @@ -219,10 +218,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : listenPort = atoi(portStr); } - // call the OAuthWebviewHandler static getter so that its instance lives in our thread - // make sure it is ready before the NodeList might need it - OAuthWebViewHandler::getInstance(); - // start the nodeThread so its event loop is running _nodeThread->start(); @@ -3522,9 +3517,6 @@ void Application::domainChanged(const QString& domainHostname) { // reset the voxels renderer _voxels.killLocalVoxels(); - - // reset the auth URL for OAuth web view handler - OAuthWebViewHandler::getInstance().clearLastAuthorizationURL(); } void Application::connectedToDomain(const QString& hostname) { diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 0889007c76..a5ad4a4c59 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -15,7 +15,6 @@ #include "Application.h" #include "Menu.h" -#include "ui/OAuthWebViewHandler.h" #include "DatagramProcessor.h" @@ -136,16 +135,11 @@ void DatagramProcessor::processDatagrams() { application->_bandwidthMeter.inputStream(BandwidthMeter::AVATARS).updateValue(incomingPacket.size()); break; } - case PacketTypeDomainOAuthRequest: { - QDataStream readStream(incomingPacket); - readStream.skipRawData(numBytesForPacketHeader(incomingPacket)); - - QUrl authorizationURL; - readStream >> authorizationURL; - - QMetaObject::invokeMethod(&OAuthWebViewHandler::getInstance(), "displayWebviewForAuthorizationURL", - Q_ARG(const QUrl&, authorizationURL)); - + case PacketTypeDomainUsernameRequest: { + // flag the domain handler so it knows to send a username signature on next check-in + // and then make it send that next check in + nodeList->getDomainHandler().setRequiresUsernameSignature(true); + nodeList->sendDomainServerCheckIn(); break; } case PacketTypeMuteEnvironment: { diff --git a/interface/src/ui/OAuthWebViewHandler.cpp b/interface/src/ui/OAuthWebViewHandler.cpp deleted file mode 100644 index 86db54afb4..0000000000 --- a/interface/src/ui/OAuthWebViewHandler.cpp +++ /dev/null @@ -1,168 +0,0 @@ -// -// OAuthWebViewHandler.cpp -// interface/src/ui -// -// Created by Stephen Birarda on 2014-05-01. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include - -#include - -#include "Application.h" - -#include "OAuthWebViewHandler.h" - -OAuthWebViewHandler& OAuthWebViewHandler::getInstance() { - static OAuthWebViewHandler sharedInstance; - return sharedInstance; -} - -OAuthWebViewHandler::OAuthWebViewHandler() : - _activeWebView(NULL), - _webViewRedisplayTimer(), - _lastAuthorizationURL() -{ - addHighFidelityRootCAToSSLConfig(); -} - -const char HIGH_FIDELITY_CA[] = "-----BEGIN CERTIFICATE-----\n" - "MIID6TCCA1KgAwIBAgIJANlfRkRD9A8bMA0GCSqGSIb3DQEBBQUAMIGqMQswCQYD\n" - "VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j\n" - "aXNjbzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVy\n" - "YXRpb25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEW\n" - "E29wc0BoaWdoZmlkZWxpdHkuaW8wHhcNMTQwMzI4MjIzMzM1WhcNMjQwMzI1MjIz\n" - "MzM1WjCBqjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNV\n" - "BAcTDVNhbiBGcmFuY2lzY28xGzAZBgNVBAoTEkhpZ2ggRmlkZWxpdHksIEluYzET\n" - "MBEGA1UECxMKT3BlcmF0aW9uczEYMBYGA1UEAxMPaGlnaGZpZGVsaXR5LmlvMSIw\n" - "IAYJKoZIhvcNAQkBFhNvcHNAaGlnaGZpZGVsaXR5LmlvMIGfMA0GCSqGSIb3DQEB\n" - "AQUAA4GNADCBiQKBgQDyo1euYiPPEdnvDZnIjWrrP230qUKMSj8SWoIkbTJF2hE8\n" - "2eP3YOgbgSGBzZ8EJBxIOuNmj9g9Eg6691hIKFqy5W0BXO38P04Gg+pVBvpHFGBi\n" - "wpqGbfsjaUDuYmBeJRcMO0XYkLCRQG+lAQNHoFDdItWAJfC3FwtP3OCDnz8cNwID\n" - "AQABo4IBEzCCAQ8wHQYDVR0OBBYEFCSv2kmiGg6VFMnxXzLDNP304cPAMIHfBgNV\n" - "HSMEgdcwgdSAFCSv2kmiGg6VFMnxXzLDNP304cPAoYGwpIGtMIGqMQswCQYDVQQG\n" - "EwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNj\n" - "bzEbMBkGA1UEChMSSGlnaCBGaWRlbGl0eSwgSW5jMRMwEQYDVQQLEwpPcGVyYXRp\n" - "b25zMRgwFgYDVQQDEw9oaWdoZmlkZWxpdHkuaW8xIjAgBgkqhkiG9w0BCQEWE29w\n" - "c0BoaWdoZmlkZWxpdHkuaW+CCQDZX0ZEQ/QPGzAMBgNVHRMEBTADAQH/MA0GCSqG\n" - "SIb3DQEBBQUAA4GBAEkQl3p+lH5vuoCNgyfa67nL0MsBEt+5RSBOgjwCjjASjzou\n" - "FTv5w0he2OypgMQb8i/BYtS1lJSFqjPJcSM1Salzrm3xDOK5pOXJ7h6SQLPDVEyf\n" - "Hy2/9d/to+99+SOUlvfzfgycgjOc+s/AV7Y+GBd7uzGxUdrN4egCZW1F6/mH\n" - "-----END CERTIFICATE-----\n"; - -void OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig() { - QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration(); - - // add the High Fidelity root CA to the list of trusted CA certificates - QByteArray highFidelityCACertificate(HIGH_FIDELITY_CA, sizeof(HIGH_FIDELITY_CA)); - sslConfig.setCaCertificates(sslConfig.caCertificates() + QSslCertificate::fromData(highFidelityCACertificate)); - - // set the modified configuration - QSslConfiguration::setDefaultConfiguration(sslConfig); -} - -const int WEB_VIEW_REDISPLAY_ELAPSED_MSECS = 5 * 1000; - -void OAuthWebViewHandler::displayWebviewForAuthorizationURL(const QUrl& authorizationURL) { - if (!_activeWebView) { - - if (!_lastAuthorizationURL.isEmpty()) { - if (_lastAuthorizationURL.host() == authorizationURL.host() - && _webViewRedisplayTimer.elapsed() < WEB_VIEW_REDISPLAY_ELAPSED_MSECS) { - // this would be re-displaying an OAuth dialog for the same auth URL inside of the redisplay ms - // so return instead - return; - } - } - - _lastAuthorizationURL = authorizationURL; - - _activeWebView = new QWebView; - - // keep the window on top and delete it when it closes - _activeWebView->setWindowFlags(Qt::Sheet); - _activeWebView->setAttribute(Qt::WA_DeleteOnClose); - - qDebug() << "Displaying QWebView for OAuth authorization at" << authorizationURL.toString(); - - AccountManager& accountManager = AccountManager::getInstance(); - - QUrl codedAuthorizationURL = authorizationURL; - - // check if we have an access token for this host - if so we can bypass login by adding it to the URL - if (accountManager.getAuthURL().host() == authorizationURL.host() - && accountManager.hasValidAccessToken()) { - - const QString ACCESS_TOKEN_QUERY_STRING_KEY = "access_token"; - - QUrlQuery authQuery(codedAuthorizationURL); - authQuery.addQueryItem(ACCESS_TOKEN_QUERY_STRING_KEY, accountManager.getAccountInfo().getAccessToken().token); - - codedAuthorizationURL.setQuery(authQuery); - } - - connect(_activeWebView.data(), &QWebView::urlChanged, this, &OAuthWebViewHandler::handleURLChanged); - - _activeWebView->load(codedAuthorizationURL); - - connect(_activeWebView->page()->networkAccessManager(), &QNetworkAccessManager::sslErrors, - this, &OAuthWebViewHandler::handleSSLErrors); - connect(_activeWebView->page()->networkAccessManager(), &QNetworkAccessManager::finished, - this, &OAuthWebViewHandler::handleReplyFinished); - connect(_activeWebView.data(), &QWebView::loadFinished, this, &OAuthWebViewHandler::handleLoadFinished); - - // connect to the destroyed signal so after the web view closes we can start a timer - connect(_activeWebView.data(), &QWebView::destroyed, this, &OAuthWebViewHandler::handleWebViewDestroyed); - } -} - -void OAuthWebViewHandler::handleSSLErrors(QNetworkReply* networkReply, const QList& errorList) { - qDebug() << "SSL Errors:" << errorList; -} - -void OAuthWebViewHandler::handleLoadFinished(bool success) { - if (success && _activeWebView->url().host() == NodeList::getInstance()->getDomainHandler().getHostname()) { - qDebug() << "OAuth authorization code passed successfully to domain-server."; - - // grab the UUID that is set as the state parameter in the auth URL - // since that is our new session UUID - QUrlQuery authQuery(_activeWebView->url()); - - const QString AUTH_STATE_QUERY_KEY = "state"; - NodeList::getInstance()->setSessionUUID(QUuid(authQuery.queryItemValue(AUTH_STATE_QUERY_KEY))); - - _activeWebView->close(); - _activeWebView = NULL; - } -} - -void OAuthWebViewHandler::handleReplyFinished(QNetworkReply* reply) { - if (_activeWebView && reply->error() != QNetworkReply::NoError) { - qDebug() << "Error loading" << reply->url() << "-" << reply->errorString(); - _activeWebView->close(); - } -} - -void OAuthWebViewHandler::handleWebViewDestroyed(QObject* destroyedObject) { - _webViewRedisplayTimer.restart(); -} - -void OAuthWebViewHandler::handleURLChanged(const QUrl& url) { - // check if this is the authorization screen - if it is then we need to show the OAuthWebViewHandler - const QString ACCESS_TOKEN_URL_REGEX_STRING = "redirect_uri=[\\w:\\/\\.]+&access_token="; - QRegExp accessTokenRegex(ACCESS_TOKEN_URL_REGEX_STRING); - - if (accessTokenRegex.indexIn(url.toString()) != -1) { - _activeWebView->show(); - } else if (url.toString() == DEFAULT_NODE_AUTH_URL.toString() + "/login") { - // this is a login request - we're going to close the webview and signal the AccountManager that we need a login - qDebug() << "data-server replied with login request. Signalling that login is required to proceed with OAuth."; - _activeWebView->close(); - AccountManager::getInstance().checkAndSignalForAccessToken(); - } -} diff --git a/interface/src/ui/OAuthWebViewHandler.h b/interface/src/ui/OAuthWebViewHandler.h deleted file mode 100644 index 1a95f17dfd..0000000000 --- a/interface/src/ui/OAuthWebViewHandler.h +++ /dev/null @@ -1,43 +0,0 @@ -// -// OAuthWebviewHandler.h -// interface/src/ui -// -// Created by Stephen Birarda on 2014-05-01. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_OAuthWebviewHandler_h -#define hifi_OAuthWebviewHandler_h - -#include - -class QWebView; - -class OAuthWebViewHandler : public QObject { - Q_OBJECT -public: - OAuthWebViewHandler(); - static OAuthWebViewHandler& getInstance(); - static void addHighFidelityRootCAToSSLConfig(); - - void clearLastAuthorizationURL() { _lastAuthorizationURL = QUrl(); } - -public slots: - void displayWebviewForAuthorizationURL(const QUrl& authorizationURL); - -private slots: - void handleSSLErrors(QNetworkReply* networkReply, const QList& errorList); - void handleLoadFinished(bool success); - void handleReplyFinished(QNetworkReply* reply); - void handleWebViewDestroyed(QObject* destroyedObject); - void handleURLChanged(const QUrl& url); -private: - QPointer _activeWebView; - QElapsedTimer _webViewRedisplayTimer; - QUrl _lastAuthorizationURL; -}; - -#endif // hifi_OAuthWebviewHandler_h \ No newline at end of file diff --git a/libraries/networking/src/DomainHandler.cpp b/libraries/networking/src/DomainHandler.cpp index 760c9f4c04..48f0112ef6 100644 --- a/libraries/networking/src/DomainHandler.cpp +++ b/libraries/networking/src/DomainHandler.cpp @@ -30,6 +30,7 @@ DomainHandler::DomainHandler(QObject* parent) : _iceServerSockAddr(), _icePeer(), _isConnected(false), + _requiresUsernameSignature(false), _handshakeTimer(NULL), _settingsObject(), _failedSettingsRequests(0) @@ -48,6 +49,7 @@ void DomainHandler::clearConnectionInfo() { } _isConnected = false; + _requiresUsernameSignature = false; emit disconnectedFromDomain(); diff --git a/libraries/networking/src/DomainHandler.h b/libraries/networking/src/DomainHandler.h index 86c6e6bc57..ecee505569 100644 --- a/libraries/networking/src/DomainHandler.h +++ b/libraries/networking/src/DomainHandler.h @@ -68,6 +68,9 @@ public: bool isConnected() const { return _isConnected; } void setIsConnected(bool isConnected); + bool requiresUsernameSignature() const { return _requiresUsernameSignature; } + void setRequiresUsernameSignature(bool requiresUsernameSignature) { _requiresUsernameSignature = requiresUsernameSignature; } + bool hasSettings() const { return !_settingsObject.isEmpty(); } void requestDomainSettings(); const QJsonObject& getSettingsObject() const { return _settingsObject; } @@ -104,6 +107,7 @@ private: HifiSockAddr _iceServerSockAddr; NetworkPeer _icePeer; bool _isConnected; + bool _requiresUsernameSignature; QTimer* _handshakeTimer; QJsonObject _settingsObject; int _failedSettingsRequests;