complete access token request flow after login window presentation

This commit is contained in:
Stephen Birarda 2014-02-18 14:27:52 -08:00
parent b87d65df30
commit b57a5cea6a
7 changed files with 107 additions and 10 deletions

View file

@ -260,6 +260,9 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
QNetworkDiskCache* cache = new QNetworkDiskCache(_networkAccessManager);
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
_networkAccessManager->setCache(cache);
// give our AccountManager access to the single QNetworkAccessManager
AccountManager::getInstance().setNetworkAccessManager(_networkAccessManager);
_window->setCentralWidget(_glWidget);

View file

@ -24,6 +24,7 @@
#include <QUuid>
#include <QWindow>
#include <AccountManager.h>
#include <UUID.h>
#include "Application.h"
@ -742,18 +743,34 @@ void Menu::loginForCurrentDomain() {
}
void Menu::showLoginForRootURL(const QUrl& rootURL) {
QInputDialog loginDialog(Application::getInstance()->getWindow());
QDialog loginDialog(Application::getInstance()->getWindow());
loginDialog.setWindowTitle("Login");
loginDialog.setLabelText("Username:");
QString username = QString();
loginDialog.setTextValue(username);
loginDialog.setWindowFlags(Qt::Sheet);
loginDialog.resize(loginDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, loginDialog.size().height());
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
loginDialog.setLayout(layout);
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);
QLineEdit* usernameLineEdit = new QLineEdit();
usernameLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
form->addRow("Username:", usernameLineEdit);
QLineEdit* passwordLineEdit = new QLineEdit();
passwordLineEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
passwordLineEdit->setEchoMode(QLineEdit::Password);
form->addRow("Password:", passwordLineEdit);
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
loginDialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
loginDialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
layout->addWidget(buttons);
int dialogReturn = loginDialog.exec();
if (dialogReturn == QDialog::Accepted && !loginDialog.textValue().isEmpty() && loginDialog.textValue() != username) {
// there has been a username change
if (dialogReturn == QDialog::Accepted && !usernameLineEdit->text().isEmpty() && !passwordLineEdit->text().isEmpty()) {
// attempt to get an access token given this username and password
AccountManager::getInstance().requestAccessToken(rootURL, usernameLineEdit->text(), passwordLineEdit->text());
}
sendFakeEnterEvent();
@ -764,9 +781,10 @@ void Menu::editPreferences() {
QDialog dialog(applicationInstance->getWindow());
dialog.setWindowTitle("Interface Preferences");
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
dialog.setLayout(layout);
QFormLayout* form = new QFormLayout();
layout->addLayout(form, 1);

View file

@ -7,7 +7,11 @@
//
#include <QtCore/QDataStream>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QMap>
#include <QtCore/QUrlQuery>
#include <QtNetwork/QNetworkRequest>
#include "PacketHeaders.h"
@ -37,4 +41,58 @@ bool AccountManager::hasValidAccessTokenForRootURL(const QUrl &rootURL) {
} else {
return true;
}
}
const QString OAUTH_CLIENT_ID_FOR_DEFAULT_ROOT_URL = "12b7b18e7b8c118707b84ff0735e57a4473b5b0577c2af44734f02e08d02829c";
void AccountManager::requestAccessToken(const QUrl& rootURL, const QString& username, const QString& password) {
if (_networkAccessManager) {
QNetworkRequest request;
QUrl grantURL = rootURL;
grantURL.setPath("/oauth/token");
QByteArray postData;
postData.append("client_id=12b7b18e7b8c118707b84ff0735e57a4473b5b0577c2af44734f02e08d02829c &");
postData.append("grant_type=password&");
postData.append("username=" + username + "&");
postData.append("password=" + password);
request.setUrl(grantURL);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestFinished);
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
}
}
void AccountManager::requestFinished() {
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
qDebug() << "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("");
_accessTokens.insert(requestReply->url(), OAuthAccessToken(rootObject));
}
} else {
// TODO: error handling
qDebug() << "Error in response for password grant -" << rootObject["error_description"].toString();
}
}
void AccountManager::requestError(QNetworkReply::NetworkError error) {
}

View file

@ -13,6 +13,7 @@
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include "OAuthAccessToken.h"
@ -23,10 +24,15 @@ public:
bool hasValidAccessTokenForRootURL(const QUrl& rootURL);
void requestAccessToken(const QUrl& rootURL, const QString& username, const QString& password);
const QString& getUsername() const { return _username; }
void setUsername(const QString& username) { _username = username; }
void setNetworkAccessManager(QNetworkAccessManager* networkAccessManager) { _networkAccessManager = networkAccessManager; }
public slots:
void requestFinished();
void requestError(QNetworkReply::NetworkError error);
signals:
void authenticationRequiredForRootURL(const QUrl& rootURL);
private:

View file

@ -52,7 +52,7 @@ void DomainInfo::setHostname(const QString& hostname) {
// re-set the sock addr to null and fire off a lookup of the IP address for this domain-server's hostname
qDebug("Looking up DS hostname %s.", _hostname.toLocal8Bit().constData());
QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup));
QHostInfo::lookupHost(_hostname, this, SLOT(completedHostnameLookup(const QHostInfo&)));
emit hostnameChanged(_hostname);
}

View file

@ -6,6 +6,8 @@
// Copyright (c) 2014 HighFidelity, Inc. All rights reserved.
//
#include <QtCore/qdebug.h>
#include "OAuthAccessToken.h"
OAuthAccessToken::OAuthAccessToken() :
@ -17,6 +19,14 @@ OAuthAccessToken::OAuthAccessToken() :
}
OAuthAccessToken::OAuthAccessToken(const QJsonObject& jsonObject) :
token(jsonObject["access_token"].toString()),
refreshToken(jsonObject["refresh_token"].toString()),
tokenType(jsonObject["token_type"].toString())
{
qDebug() << "the refresh token is" << refreshToken;
}
OAuthAccessToken::OAuthAccessToken(const OAuthAccessToken& otherToken) {
token = otherToken.token;
refreshToken = otherToken.refreshToken;

View file

@ -11,11 +11,13 @@
#include <QtCore/QObject>
#include <QtCore/QDateTime>
#include <QtCore/QJsonObject>
class OAuthAccessToken : public QObject {
Q_OBJECT
public:
OAuthAccessToken();
OAuthAccessToken(const QJsonObject& jsonObject);
OAuthAccessToken(const OAuthAccessToken& otherToken);
OAuthAccessToken& operator=(const OAuthAccessToken& otherToken);