mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-10 01:14:01 +02:00
Implement further handling of Interface OAuth2
This is preliminary, needs to be revisited in a more dynamic and clean fashion with time.
This commit is contained in:
parent
294646a141
commit
5706a42b56
3 changed files with 134 additions and 11 deletions
|
@ -25,6 +25,7 @@
|
|||
#include <UserActivityLogger.h>
|
||||
|
||||
#include "AccountManager.h"
|
||||
#include "DomainAccountManager.h"
|
||||
#include "DependencyManager.h"
|
||||
#include "DialogsManager.h"
|
||||
#include "Menu.h"
|
||||
|
@ -40,12 +41,17 @@ const QUrl LOGIN_DIALOG = PathUtils::qmlUrl("OverlayLoginDialog.qml");
|
|||
|
||||
LoginDialog::LoginDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
auto domainAccountManager = DependencyManager::get<DomainAccountManager>();
|
||||
// the login hasn't been dismissed yet if the user isn't logged in and is encouraged to login.
|
||||
#if !defined(Q_OS_ANDROID)
|
||||
connect(accountManager.data(), &AccountManager::loginComplete,
|
||||
this, &LoginDialog::handleLoginCompleted);
|
||||
connect(accountManager.data(), &AccountManager::loginFailed,
|
||||
this, &LoginDialog::handleLoginFailed);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::loginComplete,
|
||||
this, &LoginDialog::handleLoginCompleted);
|
||||
connect(domainAccountManager.data(), &DomainAccountManager::loginFailed,
|
||||
this, &LoginDialog::handleLoginFailed);
|
||||
connect(qApp, &Application::loginDialogFocusEnabled, this, &LoginDialog::focusEnabled);
|
||||
connect(qApp, &Application::loginDialogFocusDisabled, this, &LoginDialog::focusDisabled);
|
||||
connect(this, SIGNAL(dismissedLoginDialog()), qApp, SLOT(onDismissedLoginDialog()));
|
||||
|
@ -139,11 +145,7 @@ void LoginDialog::login(const QString& username, const QString& password) const
|
|||
|
||||
void LoginDialog::loginDomain(const QString& username, const QString& password, const QString& domainAuthProvider) const {
|
||||
qDebug() << "Attempting to login" << username << "into a domain through" << domainAuthProvider;
|
||||
// ####### TODO
|
||||
// DependencyManager::get<DomainAccountManager>()->requestAccessToken(username, password, domainAuthProvider);
|
||||
|
||||
// ####### TODO: It may not be necessary to pass domainAuthProvider to the login dialog and through to here because it was
|
||||
// originally provided to the QML from C++.
|
||||
DependencyManager::get<DomainAccountManager>()->requestAccessToken(username, password, domainAuthProvider);
|
||||
}
|
||||
|
||||
void LoginDialog::loginThroughOculus() {
|
||||
|
|
|
@ -11,18 +11,132 @@
|
|||
|
||||
#include "DomainAccountManager.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <SettingHandle.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QHttpMultiPart>
|
||||
|
||||
#include "DomainAccountManager.h"
|
||||
#include "NetworkingConstants.h"
|
||||
#include "OAuthAccessToken.h"
|
||||
#include "NetworkLogging.h"
|
||||
#include "NodeList.h"
|
||||
#include "udt/PacketHeaders.h"
|
||||
#include "NetworkAccessManager.h"
|
||||
|
||||
const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false;
|
||||
const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner";
|
||||
|
||||
Setting::Handle<QString> domainAccessToken {"private/domainAccessToken", "" };
|
||||
Setting::Handle<QString> domainAccessRefreshToken {"private/domainAccessToken", "" };
|
||||
Setting::Handle<int> domainAccessTokenExpiresIn {"private/domainAccessTokenExpiresIn", -1 };
|
||||
Setting::Handle<QString> domainAccessTokenType {"private/domainAccessTokenType", "" };
|
||||
|
||||
QUrl _domainAuthProviderURL;
|
||||
|
||||
// FIXME: If you try to authenticate this way on another domain, no one knows what will happen. Probably death.
|
||||
|
||||
DomainAccountManager::DomainAccountManager() {
|
||||
|
||||
connect(this, &DomainAccountManager::loginComplete, this, &DomainAccountManager::sendInterfaceAccessTokenToServer);
|
||||
}
|
||||
|
||||
void DomainAccountManager::requestAccessToken(const QString& login, const QString& password, const QString& domainAuthProvider) {
|
||||
|
||||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
|
||||
QNetworkRequest request;
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
|
||||
|
||||
_domainAuthProviderURL = domainAuthProvider;
|
||||
_domainAuthProviderURL.setPath("/oauth/token");
|
||||
|
||||
QByteArray postData;
|
||||
postData.append("grant_type=password&");
|
||||
postData.append("username=" + QUrl::toPercentEncoding(login) + "&");
|
||||
postData.append("password=" + QUrl::toPercentEncoding(password) + "&");
|
||||
postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
||||
|
||||
request.setUrl(_domainAuthProviderURL);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||
|
||||
QNetworkReply* requestReply = networkAccessManager.post(request, postData);
|
||||
connect(requestReply, &QNetworkReply::finished, this, &DomainAccountManager::requestAccessTokenFinished);
|
||||
}
|
||||
|
||||
void DomainAccountManager::requestAccessTokenFinished() {
|
||||
QNetworkReply* requestReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
|
||||
QJsonDocument jsonResponse = QJsonDocument::fromJson(requestReply->readAll());
|
||||
const QJsonObject& rootObject = jsonResponse.object();
|
||||
|
||||
if (!rootObject.contains("error")) {
|
||||
// construct an OAuthAccessToken from the json object
|
||||
|
||||
if (!rootObject.contains("access_token") || !rootObject.contains("expires_in")
|
||||
|| !rootObject.contains("token_type")) {
|
||||
// TODO: error handling - malformed token response
|
||||
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
|
||||
} else {
|
||||
// clear the path from the response URL so we have the right root URL for this access token
|
||||
QUrl rootURL = requestReply->url();
|
||||
rootURL.setPath("");
|
||||
|
||||
qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(rootURL.toString());
|
||||
|
||||
setAccessTokenFromJSON(rootObject);
|
||||
|
||||
emit loginComplete(rootURL);
|
||||
}
|
||||
} else {
|
||||
qCDebug(networking) << "Error in response for password grant -" << rootObject["error_description"].toString();
|
||||
emit loginFailed();
|
||||
}
|
||||
}
|
||||
|
||||
void DomainAccountManager::sendInterfaceAccessTokenToServer() {
|
||||
// TODO: Send successful packet to the domain-server.
|
||||
}
|
||||
|
||||
bool DomainAccountManager::accessTokenIsExpired() {
|
||||
return domainAccessTokenExpiresIn.get() != -1 && domainAccessTokenExpiresIn.get() <= QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
|
||||
bool DomainAccountManager::hasValidAccessToken() {
|
||||
QString currentDomainAccessToken = domainAccessToken.get();
|
||||
|
||||
if (currentDomainAccessToken.isEmpty() || accessTokenIsExpired()) {
|
||||
|
||||
// #######: TODO
|
||||
if (VERBOSE_HTTP_REQUEST_DEBUGGING) {
|
||||
qCDebug(networking) << "An access token is required for requests to"
|
||||
<< qPrintable(_domainAuthProviderURL.toString());
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
} else {
|
||||
|
||||
// ####### TODO::
|
||||
|
||||
// if (!_isWaitingForTokenRefresh && needsToRefreshToken()) {
|
||||
// refreshAccessToken();
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DomainAccountManager::setAccessTokenFromJSON(const QJsonObject& jsonObject) {
|
||||
domainAccessToken.set(jsonObject["access_token"].toString());
|
||||
domainAccessRefreshToken.set(jsonObject["refresh_token"].toString());
|
||||
domainAccessTokenExpiresIn.set(QDateTime::currentMSecsSinceEpoch() + (jsonObject["expires_in"].toDouble() * 1000));
|
||||
domainAccessTokenType.set(jsonObject["token_type"].toString());
|
||||
}
|
||||
|
||||
bool DomainAccountManager::checkAndSignalForAccessToken() {
|
||||
|
|
|
@ -25,15 +25,22 @@ public:
|
|||
Q_INVOKABLE bool checkAndSignalForAccessToken();
|
||||
|
||||
public slots:
|
||||
|
||||
void requestAccessToken(const QString& login, const QString& password, const QString& domainAuthProvider);
|
||||
|
||||
void requestAccessTokenFinished();
|
||||
signals:
|
||||
void authRequired();
|
||||
void loginComplete(const QUrl& authURL);
|
||||
void loginFailed();
|
||||
void logoutComplete();
|
||||
|
||||
private slots:
|
||||
|
||||
private:
|
||||
bool hasValidAccessToken();
|
||||
|
||||
bool accessTokenIsExpired();
|
||||
void setAccessTokenFromJSON(const QJsonObject&);
|
||||
void sendInterfaceAccessTokenToServer();
|
||||
};
|
||||
|
||||
#endif // hifi_DomainAccountManager_h
|
||||
|
|
Loading…
Reference in a new issue