mirror of
https://github.com/yuezk/GlobalProtect-openconnect.git
synced 2025-05-20 07:26:58 -04:00
fix: refine the authentication workflow
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWebEngineWidgets/QWebEngineProfile>
|
||||
#include <QtWebEngineWidgets/QWebEngineView>
|
||||
#include <QWebEngineCookieStore>
|
||||
#include <plog/Log.h>
|
||||
|
||||
#include "samlloginwindow.h"
|
||||
@@ -16,12 +17,20 @@ SAMLLoginWindow::SAMLLoginWindow(QWidget *parent)
|
||||
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
|
||||
webView->setUrl(QUrl("about:blank"));
|
||||
webView->setAttribute(Qt::WA_DeleteOnClose);
|
||||
// webView->page()->profile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies);
|
||||
verticalLayout->addWidget(webView);
|
||||
|
||||
webView->initialize();
|
||||
connect(webView, &EnhancedWebView::responseReceived, this, &SAMLLoginWindow::onResponseReceived);
|
||||
connect(webView, &EnhancedWebView::loadFinished, this, &SAMLLoginWindow::onLoadFinished);
|
||||
|
||||
// Show the login window automatically when exceeds the MAX_WAIT_TIME
|
||||
QTimer::singleShot(MAX_WAIT_TIME, this, [this]() {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
LOGI << "MAX_WAIT_TIME exceeded, display the login window.";
|
||||
this->show();
|
||||
});
|
||||
}
|
||||
|
||||
SAMLLoginWindow::~SAMLLoginWindow()
|
||||
@@ -37,50 +46,53 @@ void SAMLLoginWindow::closeEvent(QCloseEvent *event)
|
||||
|
||||
void SAMLLoginWindow::login(const QString samlMethod, const QString samlRequest, const QString preloingUrl)
|
||||
{
|
||||
webView->page()->profile()->cookieStore()->deleteSessionCookies();
|
||||
|
||||
if (samlMethod == "POST") {
|
||||
webView->setHtml(samlRequest, preloingUrl);
|
||||
} else if (samlMethod == "REDIRECT") {
|
||||
LOGI << "Redirect to " << samlRequest;
|
||||
webView->load(samlRequest);
|
||||
} else {
|
||||
LOGE << "Unknown saml-auth-method expected POST or REDIRECT, got " << samlMethod;
|
||||
emit fail("Unknown saml-auth-method, got " + samlMethod);
|
||||
failed = true;
|
||||
emit fail("ERR001", "Unknown saml-auth-method, got " + samlMethod);
|
||||
}
|
||||
}
|
||||
|
||||
void SAMLLoginWindow::onResponseReceived(QJsonObject params)
|
||||
{
|
||||
QString type = params.value("type").toString();
|
||||
const auto type = params.value("type").toString();
|
||||
// Skip non-document response
|
||||
if (type != "Document") {
|
||||
return;
|
||||
}
|
||||
|
||||
QJsonObject response = params.value("response").toObject();
|
||||
QJsonObject headers = response.value("headers").toObject();
|
||||
auto response = params.value("response").toObject();
|
||||
auto headers = response.value("headers").toObject();
|
||||
|
||||
LOGI << "Trying to receive from " << response.value("url").toString();
|
||||
LOGI << "Trying to receive authentication cookie from " << response.value("url").toString();
|
||||
|
||||
const QString username = headers.value("saml-username").toString();
|
||||
const QString preloginCookie = headers.value("prelogin-cookie").toString();
|
||||
const QString userAuthCookie = headers.value("portal-userauthcookie").toString();
|
||||
const auto username = headers.value("saml-username").toString();
|
||||
const auto preloginCookie = headers.value("prelogin-cookie").toString();
|
||||
const auto userAuthCookie = headers.value("portal-userauthcookie").toString();
|
||||
|
||||
this->checkSamlResult(username, preloginCookie, userAuthCookie);
|
||||
}
|
||||
|
||||
void SAMLLoginWindow::checkSamlResult(QString username, QString preloginCookie, QString userAuthCookie)
|
||||
{
|
||||
LOGI << "Checking the authentication result...";
|
||||
|
||||
if (!username.isEmpty()) {
|
||||
LOGI << "Got username from SAML response headers " << username;
|
||||
samlResult.insert("username", username);
|
||||
}
|
||||
|
||||
if (!preloginCookie.isEmpty()) {
|
||||
LOGI << "Got prelogin-cookie from SAML response headers " << preloginCookie;
|
||||
samlResult.insert("preloginCookie", preloginCookie);
|
||||
}
|
||||
|
||||
if (!userAuthCookie.isEmpty()) {
|
||||
LOGI << "Got portal-userauthcookie from SAML response headers " << userAuthCookie;
|
||||
samlResult.insert("userAuthCookie", userAuthCookie);
|
||||
}
|
||||
|
||||
@@ -94,8 +106,6 @@ void SAMLLoginWindow::checkSamlResult(QString username, QString preloginCookie,
|
||||
|
||||
emit success(samlResult);
|
||||
accept();
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,25 +118,24 @@ void SAMLLoginWindow::onLoadFinished()
|
||||
void SAMLLoginWindow::handleHtml(const QString &html)
|
||||
{
|
||||
// try to check the html body and extract from there
|
||||
const QRegularExpression regex("<saml-auth-status>(.*)</saml-auth-status>");
|
||||
const QRegularExpressionMatch match = regex.match(html);
|
||||
const QString samlAuthStatusOnBody = match.captured(1);
|
||||
const auto samlAuthStatus = parseTag("saml-auth-status", html);
|
||||
|
||||
if (samlAuthStatusOnBody == "1") {
|
||||
const QRegularExpression preloginCookieRegex("<prelogin-cookie>(.*)</prelogin-cookie>");
|
||||
const QRegularExpressionMatch preloginCookieMatch = preloginCookieRegex.match(html);
|
||||
const QString preloginCookie = preloginCookieMatch.captured(1);
|
||||
|
||||
const QRegularExpression usernameRegex("<saml-username>(.*)</saml-username>");
|
||||
const QRegularExpressionMatch usernameMatch = usernameRegex.match(html);
|
||||
const QString username = usernameMatch.captured(1);
|
||||
|
||||
const QRegularExpression userAuthCookieRegex("<portal-userauthcookie>(.*)</portal-userauthcookie>");
|
||||
const QRegularExpressionMatch userAuthCookieMatch = userAuthCookieRegex.match(html);
|
||||
const QString userAuthCookie = userAuthCookieMatch.captured(1);
|
||||
if (samlAuthStatus == "1") {
|
||||
const auto preloginCookie = parseTag("prelogin-cookie", html);
|
||||
const auto username = parseTag("saml-username", html);
|
||||
const auto userAuthCookie = parseTag("portal-userauthcookie", html);
|
||||
|
||||
checkSamlResult(username, preloginCookie, userAuthCookie);
|
||||
} else if (samlAuthStatus == "-1") {
|
||||
LOGI << "SAML authentication failed...";
|
||||
failed = true;
|
||||
emit fail("ERR002", "Authentication failed, please try again.");
|
||||
} else {
|
||||
show();
|
||||
}
|
||||
}
|
||||
|
||||
QString SAMLLoginWindow::parseTag(const QString &tag, const QString &html) {
|
||||
const QRegularExpression expression(QString("<%1>(.*)</%1>").arg(tag));
|
||||
return expression.match(html).captured(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user