mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 21:13:31 +02:00
more work on authentication, show login window when domain asks
This commit is contained in:
parent
c762b92e5a
commit
8a0136efe1
13 changed files with 165 additions and 35 deletions
domain-server/src
interface/src
libraries/shared/src
|
@ -41,7 +41,7 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
_staticAssignmentHash(),
|
||||
_assignmentQueue(),
|
||||
_hasCompletedRestartHold(false),
|
||||
_nodeAuthenticationHostname(DEFAULT_NODE_AUTH_URL)
|
||||
_nodeAuthenticationURL(DEFAULT_NODE_AUTH_URL)
|
||||
{
|
||||
const char CUSTOM_PORT_OPTION[] = "-p";
|
||||
const char* customPortString = getCmdOption(argc, (const char**) argv, CUSTOM_PORT_OPTION);
|
||||
|
@ -65,9 +65,9 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
|||
const QString NO_AUTH_OPTION = "--noAuth";
|
||||
const QString CUSTOM_AUTH_OPTION = "--customAuth";
|
||||
if ((argumentIndex = argumentList.indexOf(NO_AUTH_OPTION) != -1)) {
|
||||
_nodeAuthenticationHostname = QUrl();
|
||||
_nodeAuthenticationURL = QUrl();
|
||||
} else if ((argumentIndex = argumentList.indexOf(CUSTOM_AUTH_OPTION)) != -1) {
|
||||
_nodeAuthenticationHostname = QUrl(argumentList.value(argumentIndex + 1));
|
||||
_nodeAuthenticationURL = QUrl(argumentList.value(argumentIndex + 1));
|
||||
}
|
||||
|
||||
NodeList* nodeList = NodeList::createInstance(NodeType::DomainServer, domainServerPort);
|
||||
|
@ -254,14 +254,14 @@ void DomainServer::readAvailableDatagrams() {
|
|||
|
||||
QUuid nodeUUID = uuidFromPacketHeader(receivedPacket);
|
||||
|
||||
if (!_nodeAuthenticationHostname.isEmpty() &&
|
||||
if (!_nodeAuthenticationURL.isEmpty() &&
|
||||
(nodeUUID.isNull() || !nodeList->nodeWithUUID(nodeUUID))) {
|
||||
// this is a node we do not recognize and we need authentication - ask them to do so
|
||||
// by providing them the hostname they should authenticate with
|
||||
QByteArray authenticationRequestPacket = byteArrayWithPopluatedHeader(PacketTypeDomainServerAuthRequest);
|
||||
|
||||
QDataStream authPacketStream(&authenticationRequestPacket, QIODevice::Append);
|
||||
authPacketStream << _nodeAuthenticationHostname;
|
||||
authPacketStream << _nodeAuthenticationURL;
|
||||
|
||||
qDebug() << "Asking node at" << senderSockAddr << "to authenticate.";
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ private:
|
|||
|
||||
bool _hasCompletedRestartHold;
|
||||
|
||||
QUrl _nodeAuthenticationHostname;
|
||||
QUrl _nodeAuthenticationURL;
|
||||
private slots:
|
||||
void readAvailableDatagrams();
|
||||
void addStaticAssignmentsBackToQueueAfterRestart();
|
||||
|
|
|
@ -207,6 +207,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
|
||||
connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle);
|
||||
|
||||
connect(&AccountManager::getInstance(), SIGNAL(authenticationRequiredForRootURL(const QUrl&)),
|
||||
Menu::getInstance(), SLOT(showLoginForRootURL(const QUrl&)));
|
||||
|
||||
// read the ApplicationInfo.ini file for Name/Version/Domain information
|
||||
QSettings applicationInfo("resources/info/ApplicationInfo.ini", QSettings::IniFormat);
|
||||
|
||||
|
@ -4216,6 +4219,5 @@ void Application::takeSnapshot() {
|
|||
player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
|
||||
player->play();
|
||||
|
||||
Snapshot::saveSnapshot(_glWidget, AccountManager::getUsername(), _myAvatar->getPosition());
|
||||
}
|
||||
|
||||
Snapshot::saveSnapshot(_glWidget, AccountManager::getInstance().getUsername(), _myAvatar->getPosition());
|
||||
}
|
|
@ -89,7 +89,7 @@ Menu::Menu() :
|
|||
MenuOption::Login,
|
||||
0,
|
||||
this,
|
||||
SLOT(login())));
|
||||
SLOT(loginForCurrentDomain())));
|
||||
|
||||
addDisabledActionAndSeparator(fileMenu, "Scripts");
|
||||
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O, appInstance, SLOT(loadDialog()));
|
||||
|
@ -737,7 +737,11 @@ void sendFakeEnterEvent() {
|
|||
const int QLINE_MINIMUM_WIDTH = 400;
|
||||
const float DIALOG_RATIO_OF_WINDOW = 0.30f;
|
||||
|
||||
void Menu::login() {
|
||||
void Menu::loginForCurrentDomain() {
|
||||
showLoginForRootURL(NodeList::getInstance()->getDomainInfo().getRootAuthenticationURL());
|
||||
}
|
||||
|
||||
void Menu::showLoginForRootURL(const QUrl& rootURL) {
|
||||
QInputDialog loginDialog(Application::getInstance()->getWindow());
|
||||
loginDialog.setWindowTitle("Login");
|
||||
loginDialog.setLabelText("Username:");
|
||||
|
|
|
@ -76,7 +76,6 @@ public:
|
|||
int getMaxVoxels() const { return _maxVoxels; }
|
||||
QAction* getUseVoxelShader() const { return _useVoxelShader; }
|
||||
|
||||
|
||||
void handleViewFrustumOffsetKeyModifier(int key);
|
||||
|
||||
// User Tweakable LOD Items
|
||||
|
@ -102,6 +101,8 @@ public:
|
|||
void goToDomain(const QString newDomain);
|
||||
|
||||
public slots:
|
||||
void loginForCurrentDomain();
|
||||
void showLoginForRootURL(const QUrl& rootURL);
|
||||
void bandwidthDetails();
|
||||
void voxelStatsDetails();
|
||||
void lodTools();
|
||||
|
@ -114,7 +115,6 @@ public slots:
|
|||
|
||||
private slots:
|
||||
void aboutApp();
|
||||
void login();
|
||||
void editPreferences();
|
||||
void goToDomain();
|
||||
void goToLocation();
|
||||
|
|
|
@ -7,21 +7,34 @@
|
|||
//
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QMap>
|
||||
|
||||
#include "PacketHeaders.h"
|
||||
|
||||
#include "AccountManager.h"
|
||||
|
||||
QString AccountManager::_username = "";
|
||||
AccountManager& AccountManager::getInstance() {
|
||||
static AccountManager sharedInstance;
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
void AccountManager::processDomainServerAuthRequest(const QByteArray& packet) {
|
||||
QDataStream authPacketStream(packet);
|
||||
authPacketStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
AccountManager::AccountManager() :
|
||||
_username(),
|
||||
_accessTokens(),
|
||||
_networkAccessManager(NULL)
|
||||
{
|
||||
|
||||
// grab the hostname this domain-server wants us to authenticate with
|
||||
QString authenticationHostname;
|
||||
authPacketStream >> authenticationHostname;
|
||||
|
||||
// check if we already have an access token associated with that hostname
|
||||
}
|
||||
|
||||
bool AccountManager::hasValidAccessTokenForRootURL(const QUrl &rootURL) {
|
||||
OAuthAccessToken accessToken = _accessTokens.value(rootURL);
|
||||
|
||||
if (accessToken.token.isEmpty() || accessToken.isExpired()) {
|
||||
// emit a signal so somebody can call back to us and request an access token given a username and password
|
||||
qDebug() << "An access token is required for requests to" << qPrintable(rootURL.toString());
|
||||
emit authenticationRequiredForRootURL(rootURL);
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -10,15 +10,33 @@
|
|||
#define __hifi__AccountManager__
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
|
||||
class AccountManager {
|
||||
#include "OAuthAccessToken.h"
|
||||
|
||||
class AccountManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static void processDomainServerAuthRequest(const QByteArray& packet);
|
||||
static AccountManager& getInstance();
|
||||
|
||||
static const QString& getUsername() { return _username; }
|
||||
static void setUsername(const QString& username) { _username = username; }
|
||||
bool hasValidAccessTokenForRootURL(const QUrl& rootURL);
|
||||
|
||||
const QString& getUsername() const { return _username; }
|
||||
void setUsername(const QString& username) { _username = username; }
|
||||
|
||||
void setNetworkAccessManager(QNetworkAccessManager* networkAccessManager) { _networkAccessManager = networkAccessManager; }
|
||||
signals:
|
||||
void authenticationRequiredForRootURL(const QUrl& rootURL);
|
||||
private:
|
||||
static QString _username;
|
||||
AccountManager();
|
||||
AccountManager(AccountManager const& other); // not implemented
|
||||
void operator=(AccountManager const& other); // not implemented
|
||||
|
||||
QString _username;
|
||||
QMap<QUrl, OAuthAccessToken> _accessTokens;
|
||||
QNetworkAccessManager* _networkAccessManager;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__AccountManager__) */
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
DomainInfo::DomainInfo() :
|
||||
_sockAddr(HifiSockAddr(QHostAddress::Null, DEFAULT_DOMAIN_SERVER_PORT)),
|
||||
_requiresAuthentication(false),
|
||||
_connectionSecret(),
|
||||
_registrationToken()
|
||||
_registrationToken(),
|
||||
_rootAuthenticationURL()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QUuid>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
#include "HifiSockAddr.h"
|
||||
|
@ -34,14 +35,15 @@ public:
|
|||
|
||||
unsigned short getPort() const { return _sockAddr.getPort(); }
|
||||
|
||||
bool requiresAuthentication() const { return _requiresAuthentication; }
|
||||
void setRequiresAuthentication(bool requiresAuthentication) { _requiresAuthentication = requiresAuthentication; }
|
||||
|
||||
const QUuid& getConnectionSecret() const { return _connectionSecret; }
|
||||
void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; }
|
||||
|
||||
const QString& getRegistrationToken() const { return _registrationToken; }
|
||||
void setRegistrationToken(const QString& registrationToken);
|
||||
|
||||
const QUrl& getRootAuthenticationURL() const { return _rootAuthenticationURL; }
|
||||
void setRootAuthenticationURL(const QUrl& rootAuthenticationURL) { _rootAuthenticationURL = rootAuthenticationURL; }
|
||||
|
||||
private slots:
|
||||
void completedHostnameLookup(const QHostInfo& hostInfo);
|
||||
signals:
|
||||
|
@ -49,9 +51,9 @@ signals:
|
|||
private:
|
||||
QString _hostname;
|
||||
HifiSockAddr _sockAddr;
|
||||
bool _requiresAuthentication;
|
||||
QUuid _connectionSecret;
|
||||
QString _registrationToken;
|
||||
QUrl _rootAuthenticationURL;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__DomainInfo__) */
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtNetwork/QHostInfo>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "Assignment.h"
|
||||
#include "HifiSockAddr.h"
|
||||
#include "Logging.h"
|
||||
|
@ -197,7 +199,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
|||
}
|
||||
case PacketTypeDomainServerAuthRequest: {
|
||||
// the domain-server has asked us to auth via a data-server
|
||||
|
||||
processDomainServerAuthRequest(packet);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -471,7 +473,7 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
// send a STUN request to figure it out
|
||||
sendSTUNRequest();
|
||||
} else if (!_domainInfo.getIP().isNull()
|
||||
&& (!_domainInfo.requiresAuthentication()
|
||||
&& (_domainInfo.getRootAuthenticationURL().isEmpty()
|
||||
|| !_sessionUUID.isNull()
|
||||
|| !_domainInfo.getRegistrationToken().isEmpty()) ) {
|
||||
// construct the DS check in packet
|
||||
|
@ -562,6 +564,21 @@ int NodeList::processDomainServerList(const QByteArray& packet) {
|
|||
return readNodes;
|
||||
}
|
||||
|
||||
void NodeList::processDomainServerAuthRequest(const QByteArray& packet) {
|
||||
QDataStream authPacketStream(packet);
|
||||
authPacketStream.skipRawData(numBytesForPacketHeader(packet));
|
||||
|
||||
// grab the hostname this domain-server wants us to authenticate with
|
||||
QUrl authenticationRootURL;
|
||||
authPacketStream >> authenticationRootURL;
|
||||
|
||||
_domainInfo.setRootAuthenticationURL(authenticationRootURL);
|
||||
|
||||
if (AccountManager::getInstance().hasValidAccessTokenForRootURL(authenticationRootURL)) {
|
||||
// request a domain-server registration
|
||||
}
|
||||
}
|
||||
|
||||
void NodeList::sendAssignment(Assignment& assignment) {
|
||||
|
||||
PacketType assignmentPacketType = assignment.getCommand() == Assignment::CreateCommand
|
||||
|
|
|
@ -148,6 +148,8 @@ private:
|
|||
|
||||
void clear();
|
||||
|
||||
void processDomainServerAuthRequest(const QByteArray& packet);
|
||||
|
||||
NodeHash _nodeHash;
|
||||
QMutex _nodeHashMutex;
|
||||
QUdpSocket _nodeSocket;
|
||||
|
|
40
libraries/shared/src/OAuthAccessToken.cpp
Normal file
40
libraries/shared/src/OAuthAccessToken.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// OAuthAccessToken.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/18/2014.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "OAuthAccessToken.h"
|
||||
|
||||
OAuthAccessToken::OAuthAccessToken() :
|
||||
token(),
|
||||
refreshToken(),
|
||||
expiryTimestamp(),
|
||||
tokenType()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
OAuthAccessToken::OAuthAccessToken(const OAuthAccessToken& otherToken) {
|
||||
token = otherToken.token;
|
||||
refreshToken = otherToken.refreshToken;
|
||||
expiryTimestamp = otherToken.expiryTimestamp;
|
||||
tokenType = otherToken.tokenType;
|
||||
}
|
||||
|
||||
OAuthAccessToken& OAuthAccessToken::operator=(const OAuthAccessToken& otherToken) {
|
||||
OAuthAccessToken temp(otherToken);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void OAuthAccessToken::swap(OAuthAccessToken& otherToken) {
|
||||
using std::swap;
|
||||
|
||||
swap(token, otherToken.token);
|
||||
swap(refreshToken, otherToken.refreshToken);
|
||||
swap(expiryTimestamp, otherToken.expiryTimestamp);
|
||||
swap(tokenType, otherToken.tokenType);
|
||||
}
|
32
libraries/shared/src/OAuthAccessToken.h
Normal file
32
libraries/shared/src/OAuthAccessToken.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// OAuthAccessToken.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Stephen Birarda on 2/18/2014.
|
||||
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__OAuthAccessToken__
|
||||
#define __hifi__OAuthAccessToken__
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
class OAuthAccessToken : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OAuthAccessToken();
|
||||
OAuthAccessToken(const OAuthAccessToken& otherToken);
|
||||
OAuthAccessToken& operator=(const OAuthAccessToken& otherToken);
|
||||
|
||||
bool isExpired() { return expiryTimestamp <= QDateTime::currentMSecsSinceEpoch(); }
|
||||
|
||||
QString token;
|
||||
QString refreshToken;
|
||||
quint64 expiryTimestamp;
|
||||
QString tokenType;
|
||||
private:
|
||||
void swap(OAuthAccessToken& otherToken);
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__OAuthAccessToken__) */
|
Loading…
Reference in a new issue