mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Update to work with WordPress plugin
This commit is contained in:
parent
7da91d9557
commit
bc56eb5ac7
5 changed files with 36 additions and 46 deletions
|
@ -77,13 +77,6 @@
|
||||||
"type": "checkbox",
|
"type": "checkbox",
|
||||||
"advanced": true
|
"advanced": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "domain_access_token",
|
|
||||||
"label": "Domain API Access Token",
|
|
||||||
"help": "This is the access token that your domain-server will use to verify users and their roles. This token must grant access to that permission set on your REST API server.",
|
|
||||||
"advanced": true,
|
|
||||||
"backup": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "oauth2_url_path",
|
"name": "oauth2_url_path",
|
||||||
"label": "Authentication URL",
|
"label": "Authentication URL",
|
||||||
|
@ -95,6 +88,13 @@
|
||||||
"label": "WordPress API URL Base",
|
"label": "WordPress API URL Base",
|
||||||
"help": "The URL base that the domain server will use to make WordPress API calls. Typically \"https://oursite.com/wp-json/\". However, if using non-pretty permalinks or otherwise get a 404 error then try \"https://oursite.com/?rest_route=/\".",
|
"help": "The URL base that the domain server will use to make WordPress API calls. Typically \"https://oursite.com/wp-json/\". However, if using non-pretty permalinks or otherwise get a 404 error then try \"https://oursite.com/?rest_route=/\".",
|
||||||
"advanced": true
|
"advanced": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "plugin_client_id",
|
||||||
|
"label": "WordPress Plugin Client ID",
|
||||||
|
"help": "This is the client ID from the WordPress plugin configuration.",
|
||||||
|
"advanced": true,
|
||||||
|
"backup": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -453,6 +453,7 @@ SharedNodePointer DomainGatekeeper::processAssignmentConnectRequest(const NodeCo
|
||||||
const QString AUTHENTICATION_ENAABLED = "authentication.enable_oauth2";
|
const QString AUTHENTICATION_ENAABLED = "authentication.enable_oauth2";
|
||||||
const QString AUTHENTICATION_OAUTH2_URL_PATH = "authentication.oauth2_url_path";
|
const QString AUTHENTICATION_OAUTH2_URL_PATH = "authentication.oauth2_url_path";
|
||||||
const QString AUTHENTICATION_WORDPRESS_URL_BASE = "authentication.wordpress_url_base";
|
const QString AUTHENTICATION_WORDPRESS_URL_BASE = "authentication.wordpress_url_base";
|
||||||
|
const QString AUTHENTICATION_PLUGIN_CLIENT_ID = "authentication.plugin_client_id";
|
||||||
const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity";
|
const QString MAXIMUM_USER_CAPACITY = "security.maximum_user_capacity";
|
||||||
const QString MAXIMUM_USER_CAPACITY_REDIRECT_LOCATION = "security.maximum_user_capacity_redirect_location";
|
const QString MAXIMUM_USER_CAPACITY_REDIRECT_LOCATION = "security.maximum_user_capacity_redirect_location";
|
||||||
|
|
||||||
|
@ -553,8 +554,15 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
|
||||||
if (domainAuthURLVariant.canConvert<QString>()) {
|
if (domainAuthURLVariant.canConvert<QString>()) {
|
||||||
domainAuthURL = domainAuthURLVariant.toString();
|
domainAuthURL = domainAuthURLVariant.toString();
|
||||||
}
|
}
|
||||||
|
QString domainAuthClientID;
|
||||||
|
auto domainAuthClientIDVariant = _server->_settingsManager.valueForKeyPath(AUTHENTICATION_PLUGIN_CLIENT_ID);
|
||||||
|
if (domainAuthClientIDVariant.canConvert<QString>()) {
|
||||||
|
domainAuthClientID = domainAuthClientIDVariant.toString();
|
||||||
|
}
|
||||||
|
|
||||||
sendConnectionDeniedPacket("You lack the required domain permissions to connect to this domain.",
|
sendConnectionDeniedPacket("You lack the required domain permissions to connect to this domain.",
|
||||||
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorizedDomain, domainAuthURL);
|
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorizedDomain,
|
||||||
|
domainAuthURL + "|" + domainAuthClientID);
|
||||||
} else {
|
} else {
|
||||||
sendConnectionDeniedPacket("You lack the required metaverse permissions to connect to this domain.",
|
sendConnectionDeniedPacket("You lack the required metaverse permissions to connect to this domain.",
|
||||||
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorizedMetaverse);
|
nodeConnection.senderSockAddr, DomainHandler::ConnectionRefusedReason::NotAuthorizedMetaverse);
|
||||||
|
@ -1242,11 +1250,9 @@ void DomainGatekeeper::requestDomainUser(const QString& username, const QString&
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get data pertaining to "me", the user who generated the access token.
|
// Get data pertaining to "me", the user who generated the access token.
|
||||||
// ####### TODO: Confirm API route and data w.r.t. OAuth2 plugin's capabilities. [plugin]
|
const QString WORDPRESS_USER_ROUTE = "wp/v2/users/me";
|
||||||
const QString WORDPRESS_USER_ROUTE = "wp/v2/users/me?context=edit&_fields=id,username,roles";
|
const QString WORDPRESS_USER_QUERY = "_fields=username,roles";
|
||||||
QUrl domainUserURL = apiBase + WORDPRESS_USER_ROUTE;
|
QUrl domainUserURL = apiBase + WORDPRESS_USER_ROUTE + (apiBase.contains("?") ? "&" : "?") + WORDPRESS_USER_QUERY;
|
||||||
|
|
||||||
// ####### TODO: Append a random key to check in response? [security]
|
|
||||||
|
|
||||||
QNetworkRequest request;
|
QNetworkRequest request;
|
||||||
|
|
||||||
|
@ -1275,34 +1281,24 @@ void DomainGatekeeper::requestDomainUserFinished() {
|
||||||
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
|
|
||||||
if (200 <= httpStatus && httpStatus < 300) {
|
if (200 <= httpStatus && httpStatus < 300) {
|
||||||
// Success.
|
|
||||||
// ####### TODO: Verify Expected response. [plugin]
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
username : 'apiuser',
|
|
||||||
roles : ['subscriber'] ,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
QString username = rootObject["username"].toString().toLower();
|
QString username = rootObject["username"].toString().toLower();
|
||||||
if (_inFlightDomainUserIdentityRequests.contains(username)) {
|
if (_inFlightDomainUserIdentityRequests.contains(username)) {
|
||||||
// Success! Verified user.
|
// Success! Verified user.
|
||||||
_verifiedDomainUserIdentities.insert(username, _inFlightDomainUserIdentityRequests.value(username));
|
_verifiedDomainUserIdentities.insert(username, _inFlightDomainUserIdentityRequests.value(username));
|
||||||
_inFlightDomainUserIdentityRequests.remove(username);
|
_inFlightDomainUserIdentityRequests.remove(username);
|
||||||
|
|
||||||
|
// ####### TODO: Handle roles.
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Failure.
|
// Failure.
|
||||||
qDebug() << "Unexpected username in response for user details -" << username;
|
qDebug() << "Unexpected username in response for user details -" << username;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ####### TODO: Handle roles if available. [plugin]
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Failure.
|
// Failure.
|
||||||
|
|
||||||
// ####### TODO: Error fields to report. [plugin]
|
|
||||||
qDebug() << "Error in response for user details -" << httpStatus << requestReply->error()
|
qDebug() << "Error in response for user details -" << httpStatus << requestReply->error()
|
||||||
<< "-" << rootObject["error"].toString();
|
<< "-" << rootObject["error"].toString() << rootObject["error_description"].toString();
|
||||||
|
|
||||||
_inFlightDomainUserIdentityRequests.clear();
|
_inFlightDomainUserIdentityRequests.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
// FIXME: Generalize to other OAuth2 sources for domain login.
|
// FIXME: Generalize to other OAuth2 sources for domain login.
|
||||||
|
|
||||||
const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false;
|
const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false;
|
||||||
const QString DOMAIN_ACCOUNT_MANAGER_REQUESTED_SCOPE = "foo bar"; // ####### TODO: WordPress plugin's required scope. [plugin]
|
|
||||||
// ####### TODO: Should scope be configured in domain server settings? [plugin]
|
|
||||||
|
|
||||||
// ####### TODO: Add storing domain URL and check against it when retrieving values?
|
// ####### TODO: Add storing domain URL and check against it when retrieving values?
|
||||||
// ####### TODO: Add storing _authURL and check against it when retrieving values?
|
// ####### TODO: Add storing _authURL and check against it when retrieving values?
|
||||||
|
@ -71,15 +69,15 @@ void DomainAccountManager::requestAccessToken(const QString& username, const QSt
|
||||||
|
|
||||||
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
|
request.setHeader(QNetworkRequest::UserAgentHeader, NetworkingConstants::VIRCADIA_USER_AGENT);
|
||||||
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
// ####### TODO: WordPress plugin's authorization requirements. [plugin]
|
|
||||||
request.setRawHeader(QByteArray("Authorization"), QByteArray("Basic b2F1dGgtY2xpZW50LTE6b2F1dGgtY2xpZW50LXNlY3JldC0x"));
|
|
||||||
|
|
||||||
|
// miniOrange WordPress API Authentication plugin:
|
||||||
|
// - Requires "client_id" parameter.
|
||||||
|
// - Ignores "state" parameter.
|
||||||
QByteArray formData;
|
QByteArray formData;
|
||||||
formData.append("grant_type=password&");
|
formData.append("grant_type=password&");
|
||||||
formData.append("username=" + QUrl::toPercentEncoding(username) + "&");
|
formData.append("username=" + QUrl::toPercentEncoding(username) + "&");
|
||||||
formData.append("password=" + QUrl::toPercentEncoding(password) + "&");
|
formData.append("password=" + QUrl::toPercentEncoding(password) + "&");
|
||||||
formData.append("scope=" + DOMAIN_ACCOUNT_MANAGER_REQUESTED_SCOPE);
|
formData.append("client_id=" + _clientID);
|
||||||
// ####### TODO: Include state? [plugin]
|
|
||||||
|
|
||||||
request.setUrl(_authURL);
|
request.setUrl(_authURL);
|
||||||
|
|
||||||
|
@ -100,20 +98,13 @@ void DomainAccountManager::requestAccessTokenFinished() {
|
||||||
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
auto httpStatus = requestReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
||||||
if (200 <= httpStatus && httpStatus < 300) {
|
if (200 <= httpStatus && httpStatus < 300) {
|
||||||
|
|
||||||
// ####### TODO: Process response state? [plugin]
|
// miniOrange plugin provides no scope.
|
||||||
// ####### TODO: Process response scope? [plugin]
|
|
||||||
|
|
||||||
// ####### TODO: Which method are the tokens provided in? [plugin]
|
|
||||||
if (rootObject.contains("access_token")) {
|
if (rootObject.contains("access_token")) {
|
||||||
// Success.
|
// Success.
|
||||||
|
|
||||||
QUrl rootURL = requestReply->url();
|
QUrl rootURL = requestReply->url();
|
||||||
rootURL.setPath("");
|
rootURL.setPath("");
|
||||||
|
|
||||||
setTokensFromJSON(rootObject, rootURL);
|
setTokensFromJSON(rootObject, rootURL);
|
||||||
|
|
||||||
emit loginComplete();
|
emit loginComplete();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Failure.
|
// Failure.
|
||||||
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
|
qCDebug(networking) << "Received a response for password grant that is missing one or more expected values.";
|
||||||
|
@ -122,10 +113,8 @@ void DomainAccountManager::requestAccessTokenFinished() {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Failure.
|
// Failure.
|
||||||
|
qCDebug(networking) << "Error in response for password grant -" << httpStatus << requestReply->error()
|
||||||
// ####### TODO: Error object fields to report. [plugin]
|
<< "-" << rootObject["error"].toString() << rootObject["error_description"].toString();
|
||||||
qCDebug(networking) << "Error in response for password grant -" << httpStatus << requestReply->error()
|
|
||||||
<< "_" << rootObject["error"].toString();
|
|
||||||
emit loginFailed();
|
emit loginFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,6 +162,7 @@ void DomainAccountManager::setTokensFromJSON(const QJsonObject& jsonObject, cons
|
||||||
|
|
||||||
// ####### TODO: Enable and use these.
|
// ####### TODO: Enable and use these.
|
||||||
// ####### TODO: Protect these per AccountManager?
|
// ####### TODO: Protect these per AccountManager?
|
||||||
|
// ######: TODO: clientID needed?
|
||||||
/*
|
/*
|
||||||
qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(url.toString());
|
qCDebug(networking) << "Storing a domain account with access-token for" << qPrintable(url.toString());
|
||||||
domainAccessToken.set(jsonObject["access_token"].toString());
|
domainAccessToken.set(jsonObject["access_token"].toString());
|
||||||
|
|
|
@ -24,6 +24,7 @@ public:
|
||||||
DomainAccountManager();
|
DomainAccountManager();
|
||||||
|
|
||||||
void setAuthURL(const QUrl& authURL);
|
void setAuthURL(const QUrl& authURL);
|
||||||
|
void setClientID(const QString& clientID) { _clientID = clientID; }
|
||||||
|
|
||||||
QString getUsername() { return _username; }
|
QString getUsername() { return _username; }
|
||||||
QString getAccessToken() { return _access_token; }
|
QString getAccessToken() { return _access_token; }
|
||||||
|
@ -51,6 +52,7 @@ private:
|
||||||
void sendInterfaceAccessTokenToServer();
|
void sendInterfaceAccessTokenToServer();
|
||||||
|
|
||||||
QUrl _authURL;
|
QUrl _authURL;
|
||||||
|
QString _clientID;
|
||||||
QString _username; // ####### TODO: Store elsewhere?
|
QString _username; // ####### TODO: Store elsewhere?
|
||||||
QString _access_token; // ####... ""
|
QString _access_token; // ####... ""
|
||||||
QString _refresh_token; // ####... ""
|
QString _refresh_token; // ####... ""
|
||||||
|
|
|
@ -589,7 +589,9 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer<Rec
|
||||||
|
|
||||||
auto accountManager = DependencyManager::get<DomainAccountManager>();
|
auto accountManager = DependencyManager::get<DomainAccountManager>();
|
||||||
if (!extraInfo.isEmpty()) {
|
if (!extraInfo.isEmpty()) {
|
||||||
accountManager->setAuthURL(extraInfo);
|
auto extraInfoComponents = extraInfo.split("|");
|
||||||
|
accountManager->setAuthURL(extraInfoComponents.value(0));
|
||||||
|
accountManager->setClientID(extraInfoComponents.value(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_hasCheckedForDomainAccessToken) {
|
if (!_hasCheckedForDomainAccessToken) {
|
||||||
|
|
Loading…
Reference in a new issue