Send OAuth2 username and tokens to domain server

This commit is contained in:
David Rowe 2020-08-01 18:57:21 +12:00
parent aff3275207
commit 15c6baceb8
6 changed files with 61 additions and 28 deletions

View file

@ -95,7 +95,7 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
node = processAssignmentConnectRequest(nodeConnection, pendingAssignment->second);
} else if (!STATICALLY_ASSIGNED_NODES.contains(nodeConnection.nodeType)) {
QByteArray usernameSignature;
QByteArray domainUsernameSignature;
QString domainTokens;
if (message->getBytesLeftToRead() > 0) {
// read username from packet
@ -110,14 +110,14 @@ void DomainGatekeeper::processConnectRequestPacket(QSharedPointer<ReceivedMessag
packetStream >> domainUsername;
if (message->getBytesLeftToRead() > 0) {
// Read domain signature from packet.
packetStream >> domainUsernameSignature;
// Read domain tokens from packet.
packetStream >> domainTokens;
}
}
}
}
node = processAgentConnectRequest(nodeConnection, username, usernameSignature, domainUsername, domainUsernameSignature);
node = processAgentConnectRequest(nodeConnection, username, usernameSignature, domainUsername, domainTokens);
}
if (node) {
@ -452,7 +452,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
const QString& username,
const QByteArray& usernameSignature,
const QString& domainUsername,
const QByteArray& domainUsernameSignature) {
const QString& domainTokens) {
auto limitedNodeList = DependencyManager::get<LimitedNodeList>();
@ -502,17 +502,18 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
QString verifiedDomainUsername;
QStringList verifiedDomainUserGroups;
if (domainHasLogin() && !domainUsername.isEmpty()) {
if (domainUsernameSignature.isEmpty()) {
if (domainTokens.isEmpty()) {
// User is attempting to prove their domain identity.
// ####### TODO: OAuth2 corollary of metaverse code, above.
getDomainGroupMemberships(domainUsernameSignature); // Optimistically get started on group memberships.
// ####### TODO: Do the following now? Probably can't!
//getDomainGroupMemberships(domainUsername); // Optimistically get started on group memberships.
#ifdef WANT_DEBUG
qDebug() << "stalling login because we have no domain username-signature:" << domainUsername;
#endif
return SharedNodePointer();
} else if (verifyDomainUserSignature(domainUsername, domainUsernameSignature, nodeConnection.senderSockAddr)) {
} else if (verifyDomainUserSignature(domainUsername, domainTokens, nodeConnection.senderSockAddr)) {
// User's domain identity is confirmed.
getDomainGroupMemberships(domainUsername);
verifiedDomainUsername = domainUsername.toLower();
@ -742,10 +743,10 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username,
}
bool DomainGatekeeper::verifyDomainUserSignature(const QString& domainUsername,
const QByteArray& domainUsernameSignature,
const QString& domainTokens,
const HifiSockAddr& senderSockAddr) {
// ####### TODO: Verify via domain OAuth2.
// ####### TODO: Verify response from domain OAuth2 request to WordPress, if it's arrived yet.
bool success = true;
if (success) {
return true;

View file

@ -79,13 +79,13 @@ private:
const QString& username,
const QByteArray& usernameSignature,
const QString& domainUsername,
const QByteArray& domainUsernameSignature);
const QString& domainTokens);
SharedNodePointer addVerifiedNodeFromConnectRequest(const NodeConnectionData& nodeConnection);
bool verifyUserSignature(const QString& username, const QByteArray& usernameSignature,
const HifiSockAddr& senderSockAddr);
bool verifyDomainUserSignature(const QString& domainUsername, const QByteArray& domainUsernameSignature,
bool verifyDomainUserSignature(const QString& domainUsername, const QString& domainUsernameSignature,
const HifiSockAddr& senderSockAddr);
bool isWithinMaxCapacity();

View file

@ -11,6 +11,8 @@
#include "DomainAccountManager.h"
// ####### TODO: Check that all #includes are still needed.
#include <SettingHandle.h>
#include <QTimer>
@ -43,7 +45,12 @@ Setting::Handle<int> domainAccessTokenExpiresIn {"private/domainAccessTokenExpir
Setting::Handle<QString> domainAccessTokenType {"private/domainAccessTokenType", "" };
DomainAccountManager::DomainAccountManager() {
DomainAccountManager::DomainAccountManager() :
_authURL(),
_username(),
_access_token(),
_refresh_token()
{
connect(this, &DomainAccountManager::loginComplete, this, &DomainAccountManager::sendInterfaceAccessTokenToServer);
}
@ -57,8 +64,11 @@ void DomainAccountManager::setAuthURL(const QUrl& authURL) {
}
}
void DomainAccountManager::requestAccessToken(const QString& login, const QString& password) {
void DomainAccountManager::requestAccessToken(const QString& username, const QString& password) {
_username = username;
_access_token = "";
_refresh_token = "";
QNetworkRequest request;
@ -69,7 +79,7 @@ void DomainAccountManager::requestAccessToken(const QString& login, const QStrin
QByteArray formData;
formData.append("grant_type=password&");
formData.append("username=" + QUrl::toPercentEncoding(login) + "&");
formData.append("username=" + QUrl::toPercentEncoding(username) + "&");
formData.append("password=" + QUrl::toPercentEncoding(password) + "&");
formData.append("scope=" + DOMAIN_ACCOUNT_MANAGER_REQUESTED_SCOPE);
// ####### TODO: Include state?
@ -122,7 +132,7 @@ void DomainAccountManager::requestAccessTokenFinished() {
}
void DomainAccountManager::sendInterfaceAccessTokenToServer() {
// TODO: Send successful packet to the domain-server.
emit newTokens();
}
bool DomainAccountManager::accessTokenIsExpired() {
@ -159,7 +169,11 @@ bool DomainAccountManager::hasValidAccessToken() {
}
void DomainAccountManager::setAccessTokenFromJSON(const QJsonObject& jsonObject) {
_access_token = jsonObject["access_token"].toString();
_refresh_token = jsonObject["refresh_token"].toString();
// ####### TODO: Enable and use these.
// ####### TODO: Protect these per AccountManager?
/*
domainAccessToken.set(jsonObject["access_token"].toString());
domainAccessRefreshToken.set(jsonObject["refresh_token"].toString());

View file

@ -25,10 +25,14 @@ public:
void setAuthURL(const QUrl& authURL);
QString getUsername() { return _username; }
QString getAccessToken() { return _access_token; }
QString getRefreshToken() { return _refresh_token; }
Q_INVOKABLE bool checkAndSignalForAccessToken();
public slots:
void requestAccessToken(const QString& login, const QString& password);
void requestAccessToken(const QString& username, const QString& password);
void requestAccessTokenFinished();
signals:
@ -36,6 +40,7 @@ signals:
void loginComplete(const QUrl& authURL);
void loginFailed();
void logoutComplete();
void newTokens();
private slots:
@ -46,6 +51,9 @@ private:
void sendInterfaceAccessTokenToServer();
QUrl _authURL;
QString _username; // ####### TODO: Store elsewhere?
QString _access_token; // ####... ""
QString _refresh_token; // ####... ""
};
#endif // hifi_DomainAccountManager_h

View file

@ -34,6 +34,7 @@
#include "AddressManager.h"
#include "Assignment.h"
#include "AudioHelpers.h"
#include "DomainAccountManager.h"
#include "HifiSockAddr.h"
#include "FingerprintUtils.h"
@ -104,6 +105,13 @@ NodeList::NodeList(char newOwnerType, int socketListenPort, int dtlsListenPort)
// clear our NodeList when logout is requested
connect(accountManager.data(), &AccountManager::logoutComplete , this, [this]{ reset("Logged out"); });
// Only used in Interface.
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
if (domainAccountManager) {
_hasDomainAccountManager = true;
connect(domainAccountManager.data(), &DomainAccountManager::newTokens, this, &NodeList::sendDomainServerCheckIn);
}
// anytime we get a new node we will want to attempt to punch to it
connect(this, &LimitedNodeList::nodeAdded, this, &NodeList::startNodeHolePunch);
connect(this, &LimitedNodeList::nodeSocketUpdated, this, &NodeList::startNodeHolePunch);
@ -468,6 +476,7 @@ void NodeList::sendDomainServerCheckIn() {
packetStream << _ownerType.load() << publicSockAddr << localSockAddr << _nodeTypesOfInterest.toList();
packetStream << DependencyManager::get<AddressManager>()->getPlaceName();
// ####### TODO: Also send if need to send new domainLogin data?
if (!domainIsConnected) {
DataServerAccountInfo& accountInfo = accountManager->getAccountInfo();
packetStream << accountInfo.getUsername();
@ -477,21 +486,20 @@ void NodeList::sendDomainServerCheckIn() {
const QByteArray& usernameSignature = accountManager->getAccountInfo().getUsernameSignature(connectionToken);
packetStream << usernameSignature;
} else {
packetStream << QString(""); // Placeholder in case have domainUsername.
// ####### TODO: Only append if are going to send domain username?
packetStream << QString(""); // Placeholder in case have domain username.
}
} else {
packetStream << QString(""); // Placeholder in case have domainUsername.
// ####### TODO: Only append if are going to send domainUsername?
packetStream << QString("") << QString(""); // Placeholders in case have domain username.
}
// ####### TODO: Send domain username and signature if domain has these and aren't logged in.
// ####### If get into difficulties, could perhaps send domain's username and signature instead of metaverse.
bool domainLoginIsConnected = false;
if (!domainLoginIsConnected) {
if (false) { // ####### For testing, false causes user to be considered "not logged in".
packetStream << QString("a@b.c");
if (true) { // ####### For testing, false is unhandled at this stage.
packetStream << QString("signature"); // #######: Consider "logged in" if this is sent during testing.
}
// Send domain domain login data from Interface to domain server.
if (_hasDomainAccountManager) {
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
if (!domainAccountManager->getUsername().isEmpty()) {
packetStream << domainAccountManager->getUsername();
packetStream << (domainAccountManager->getAccessToken() + ":" + domainAccountManager->getRefreshToken());
}
}

View file

@ -196,6 +196,8 @@ private:
#if (PR_BUILD || DEV_BUILD)
bool _shouldSendNewerVersion { false };
#endif
bool _hasDomainAccountManager { false };
};
#endif // hifi_NodeList_h