SSO-Problem: Fehlende SSO- oder SIG-Parameter

Hallo, ich habe ein Problem mit Discourse SSO. Was mache ich falsch? Mein Code extrahiert problemlos von meiner anderen Plattform. Allerdings bekomme ich keinen Nonce.


// Fehlerprotokollierung zur Fehlerbehebung aktivieren
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// Init-Datei laden
require_once '/init.php'; // Aktualisieren Sie diesen Pfad basierend auf Ihrer Plattform-Einrichtung

// Discourse Connect Secret Key und URL zum Zurücksenden der Nutzlast
$sso_secret = 'keyhere'; // Ersetzen Sie dies durch Ihren Discourse Shared Secret Key
$discourse_url = 'https://urlhere.com/session/sso_login'; // Ersetzen Sie dies durch Ihre Discourse-URL

// Sitzung starten, um den Anmeldestatus des Plattform-Benutzers zu überprüfen
session_start();

// Überprüfen, ob der Benutzer angemeldet ist
if (!isset($_SESSION['uid'])) {
    // Wenn der Benutzer nicht angemeldet ist, zur Anmeldeseite der Plattform weiterleiten
    header('Location: /clientarea.php');
    exit;
}

// Debug: Eingehende Anfrageparameter protokollieren
error_log("Empfangene GET-Parameter: " . print_r($_GET, true));

// Überprüfen, ob wir die Parameter 'sso' und 'sig' von Discourse erhalten haben
if (!isset($_GET['sso']) || !isset($_GET['sig'])) {
    error_log("Fehlende SSO- oder SIG-Parameter.");
    header('Location: /clientarea.php');
    exit;
}

// Die SSO-Signatur mit dem Secret Key validieren
$sso = $_GET['sso'];
$sig = $_GET['sig'];
$expected_sig = hash_hmac('sha256', $sso, $sso_secret);

if ($sig !== $expected_sig) {
    error_log("Ungültige SSO-Signatur. Erwartet: $expected_sig, Empfangen: $sig");
    header('Location: /clientarea.php');
    exit;
}

// Plattform-Client-Details abrufen
$clientDetails = localAPI('getclientsdetails', ['clientid' => $_SESSION['uid']], 'admin');
if ($clientDetails['result'] !== 'success' || !isset($clientDetails['userid'])) {
    error_log("Fehler beim Abrufen der Plattform-Client-Details.");
    header('Location: /clientarea.php');
    exit;
}

// Benutzerdetails extrahieren
$userId = $clientDetails['userid'];
$email = $clientDetails['email'];
$firstName = $clientDetails['firstname'];
$lastName = $clientDetails['lastname'];
$username = $firstName . ' ' . $lastName;

// Die SSO-Nutzlast dekodieren
$sso_payload = base64_decode($sso);
parse_str($sso_payload, $sso_params);

if (!isset($sso_params['nonce'])) {
    error_log("Nonce fehlt in der SSO-Nutzlast.");
    header('Location: /clientarea.php');
    exit;
}

// Die Rückgabe-SSO-Nutzlast mit Benutzerdetails vorbereiten
$return_payload = [
    'nonce' => $sso_params['nonce'],
    'email' => $email,
    'external_id' => $userId,
    'username' => $username,
    'name' => $firstName . ' ' . $lastName,
    'admin' => 0, // Auf 1 setzen, wenn der Benutzer ein Administrator ist, andernfalls auf 0 lassen
    'moderator' => 0 // Auf 1 setzen, wenn der Benutzer ein Moderator ist, andernfalls auf 0 lassen
];

// Die Rückgabe-Nutzlast Base64-codieren
$query_string = http_build_query($return_payload);
$encoded_payload = base64_encode($query_string);

// Die codierte Nutzlast mit dem Discourse-Secret signieren
$return_sig = hash_hmac('sha256', $encoded_payload, $sso_secret);

// Debug: Nutzlast und Signatur protokollieren
error_log("Rückgabe-Nutzlast: " . print_r($return_payload, true));
error_log("Codierte Nutzlast: $encoded_payload");
error_log("Rückgabe-Signatur: $return_sig");

// Zu Discourse mit der signierten Nutzlast weiterleiten
header("Location: $discourse_url?sso=" . urlencode($encoded_payload) . "&sig=" . urlencode($return_sig));
exit;

Fehlerprotokolle:

[25-Sep-2024 14:50:17 UTC] Fehlende SSO- oder SIG-Parameter.
[25-Sep-2024 14:53:59 UTC] Empfangene GET-Parameter: Array
(
[sso] => nonce_from_discourse
)

[25-Sep-2024 14:53:59 UTC] Fehlende SSO- oder SIG-Parameter.

Ich bin mir nicht sicher, warum?

Ich bin mir auch nicht sicher. Ist DiscourseConnect auf Ihrer Discourse-Site konfiguriert? Wie kommen Benutzer zu der URL, die von diesem Code verarbeitet wird?

Wenn Sie den Authentifizierungsprozess mit dem geöffneten Inspektionswerkzeug Ihres Browsers im Netzwerk-Tab durchlaufen, erhalten Sie möglicherweise Details darüber, was vor sich geht.

Danke für die Antwort.

Ich versuche, mich in WHMCS zu integrieren. Ich habe alles im Code entsprechend eingerichtet und die Einstellungen in Discourse aktiviert.

Ich kann einen Teil der Antwort erhalten, aber das Sig fehlt. Ich dachte, es könnte ein Dekodierungsfehler sein, da es eine Diskrepanz zwischen den beiden Systemen zu geben scheint.

Das ist eigentlich nicht meine Kernkompetenz, ich gebe mein Bestes, es zusammenzufügen, aber ich zerbreche mir seit zwei Tagen den Kopf. Ich sehe meinen Fehler nicht.

Ich habe so viel wie möglich debuggt, Discourse neu aufgebaut. Schrittweise Protokollierung. ChatGPT ausprobiert. Mit dem WordPress-Plugin-Code verglichen. Ratlos.

Es scheint wahrscheinlich, dass etwas nicht richtig konfiguriert ist. Versuchen Sie vielleicht, einen Schritt zurückzutreten. Ich habe derzeit keine SSO-Anbieter-Website auf meinem lokalen System konfiguriert, aber das könnte Ihnen vielleicht weiterhelfen.

Stellen Sie auf Discourse sicher, dass die folgenden Einstellungen konfiguriert sind:

Die Einstellung discourse connect url sollte auf die URL gesetzt werden, die den von Ihnen geposteten Code verarbeitet.

Setzen Sie die Einstellung discourse connect secret auf eine Zeichenkette, die mindestens 10 Zeichen lang ist. Beachten Sie, dass Sie die 7 Zeichen lange Zeichenkette keyhere fest in den von Ihnen geposteten Code einprogrammiert haben. Ich gehe davon aus, dass Sie diesen Wert ändern, wenn Sie den Code ausführen. Setzen Sie ihn auf denselben Wert, den Sie in Discourse eingegeben haben.

Melden Sie sich nun von Ihrer Discourse-Website ab. Öffnen Sie die Web-Inspektor-Registerkarte “Netzwerk” Ihres Browsers. Klicken Sie auf die Schaltfläche “Anmelden” auf Discourse. Sie sollten Anfragen sehen, die den ersten beiden Anfragen aus dem folgenden Screenshot ähneln:

Die erste Anfrage geht an http://forum.example.com/session/sso?return_path=%2F

Die nächste Anfrage sollte an https://example.com/?sso=<sso_payload_sent_from_discourse>&sig=<sso_signature> gehen.

example.com und forum.example.com sollten auf die tatsächlichen Domains gesetzt werden, die Sie verwenden.

Wenn alles richtig konfiguriert ist, würde ich erwarten, dass die Werte der Parameter sso und sig den Variablen zugewiesen werden, die Sie hier festgelegt haben:

$sso = $_GET['sso'];
$sig = $_GET['sig'];

Wenn ich Sie wäre, würde ich wahrscheinlich den Rest des Codes auskommentieren und nur bestätigen, dass Sie die Nutzlast empfangen und den Variablen zuweisen können.

Wenn DiscourseConnect aktiviert ist, können Sie sich wieder bei Ihrer Discourse-Website anmelden, indem Sie die Route /u/admin-login aufrufen. Wenn Sie Zugriff auf die Rails-Konsole der Discourse-Website haben, können Sie sich auch anmelden, indem Sie DiscourseConnect von der Rails-Konsole aus deaktivieren:

SiteSetting.enable_discourse_connect = false

Es ist möglich, dass es weiter unten im von Ihnen geposteten Code Fehler gibt. Zum Beispiel glaube ich, dass Sie urldecode auf den Wert des sso-Parameters anwenden müssen, bevor Sie die erwartete Signatur generieren. Schauen Sie sich an, wie das WP Discourse-Plugin damit umgeht:

$payload in der obigen Funktion ist nur der Wert des sso-Query-Parameters, nachdem er hier bereinigt wurde: wp-discourse/lib/sso-provider/discourse-sso.php at main · discourse/wp-discourse · GitHub.

1 „Gefällt mir“