Einen DiscourseConnect-Anmeldelink erstellen

:bookmark: Diese Dokumentation erklärt, wie man auf einer DiscourseConnect-Anbieterseite Links erstellt, die Benutzer bei Discourse anmelden und sie zu einer bestimmten Discourse-URL weiterleiten.
:person_raising_hand: Erforderlicher Benutzerrang: Administrator

Seiten, die DiscourseConnect verwenden, können auf ihrer DiscourseConnect-Anbieterseite Links hinzufügen, die Benutzer bei Discourse anmelden und sie zu einer bestimmten Discourse-URL weiterleiten. Dies geschieht durch die Erstellung von Links, die auf die Route /session/sso verweisen und einen return_path-Parameter enthalten, der auf den Pfad der Discourse-Seite gesetzt ist, auf der die Benutzer landen sollen.
Die href-Eigenschaft des Links sollte die unten angegebene Form haben, wobei der Pfad, auf dem die Benutzer landen sollen, für <relativer_pfad> eingesetzt wird:

https://forum.example.com/session/sso?return_path=<relativer_pfad>

Ein Beispiel-Anker-Tag, das einen Benutzer anmeldet und ihn zur Startseite einer Discourse-Seite weiterleitet:

<a href="https://forum.example.com/session/sso?return_path=/">Community</a>

Ein Beispiel-Anker-Tag, das einen Benutzer anmeldet und ihn zur Seite „Top-Themen“ weiterleitet:

<a href="https://forum.example.com/session/sso?return_path=/top">Top Topics</a>

Wie der return_path auf Discourse gespeichert wird

Discourse speichert den Wert des return_path-Parameters in der Serversitzung, indiziert durch die SSO-Nonce, die generiert wird, wenn ein Benutzer die Route /session/sso besucht. Am Ende des DiscourseConnect-Authentifizierungsprozesses sucht Discourse anhand der Nonce den return_path nach und leitet Benutzer zu diesem Pfad weiter.

Den Prozess für authentifizierte Benutzer nahtlos gestalten

Wenn ein Benutzer die Discourse-Route /session/sso besucht, wird er auf die URL weitergeleitet, die durch die Site-Einstellung discourse connect url festgelegt ist. Der DiscourseConnect-Anbieter übernimmt dann den Authentifizierungsprozess auf die gleiche Weise, wie er es tun würde, wenn der Benutzer auf die Discourse Login-Schaltfläche geklickt hätte.

Damit der Authentifizierungsprozess für Benutzer, die auf der Authentifizierungsanbieterseite bereits angemeldet sind, nahtlos verläuft, muss der DiscourseConnect-Code des Authentifizierungsanbieters prüfen, ob der Benutzer angemeldet ist oder nicht. Wenn der Benutzer nicht angemeldet ist, durchläuft er den Anmeldeprozess des Authentifizierungsanbieters. Wenn der Benutzer bereits angemeldet ist, wird der Anmeldeprozess auf der Website des Authentifizierungsanbieters übersprungen.

Hier ist ein kommentiertes Beispiel, das Code aus dem WP Discourse Plugin verwendet. Es zeigt, wie authentifizierte Benutzer anders behandelt werden können als nicht authentifizierte Benutzer:

public function sso_parse_request( $wp ) {
    // Prüfen, ob Single Sign-On (SSO) in den Plugin-Optionen aktiviert ist
    if ( empty( $this->options['enable-sso'] ) ) {
        return null;
    }

    // Behandle alle Abmeldeanforderungen, bevor mit SSO fortgefahren wird
    $this->handle_logout_request();

    // Prüfen, ob die Parameter 'sso' und 'sig' in den Abfragevariablen vorhanden sind
    if ( array_key_exists( 'sso', $wp->query_vars ) && array_key_exists( 'sig', $wp->query_vars ) ) {
        // Die 'sso'-Nutzdaten und die Signatur bereinigen, um sicherzustellen, dass sie sicher verwendet werden können
        $payload = sanitize_text_field( $wp->query_vars['sso'] );
        $sig     = sanitize_text_field( $wp->query_vars['sig'] );

        // Wenn der Benutzer nicht in WordPress angemeldet ist, zur Anmeldeseite weiterleiten
        // Dies stellt sicher, dass Benutzer ohne aktive Sitzung zuerst aufgefordert werden, sich in WordPress anzumelden
        if ( ! is_user_logged_in() ) {
            // Eine URL konstruieren, zu der nach der Anmeldung zurückgekehrt werden soll
            $redirect = add_query_arg( $payload, $sig );
            // Die WordPress-Anmelde-URL mit dem Weiterleitungs-Parameter generieren
            $login    = wp_login_url( esc_url_raw( $redirect ) );

            // Eine Aktion auslösen, bevor zur Anmeldung weitergeleitet wird (optional zum Protokollieren oder für benutzerdefinierte Aktionen)
            do_action( 'wpdc_sso_before_login_redirect', $redirect, $login );

            // Zur WordPress-Anmeldeseite weiterleiten
            return $this->redirect_to( $login );
        } else {
            // Wenn der Benutzer in WordPress bereits authentifiziert ist, den Anmeldevorgang überspringen
            // und mit der Validierung der SSO-Nutzdaten und der Signatur fortfahren.
            $sso_secret = $this->options['sso-secret'];
            $sso        = new SSO( $sso_secret );
            
            // Die Nutzdaten und die Signatur mithilfe des SSO-Geheimnisses validieren
            if ( ! ( $sso->validate( $payload, $sig ) ) ) {
                // Ungültige SSO-Anforderungen behandeln
                return $this->handle_error( 'parse_request.invalid_sso' );
            }

            // Den aktuell angemeldeten WordPress-Benutzer abrufen
            $current_user = wp_get_current_user();
            // SSO-Parameter mithilfe der Daten des angemeldeten Benutzers vorbereiten
            $params       = $this->get_sso_params( $current_user );

            try {
                // Eine Nonce aus den Nutzdaten generieren und den SSO-Anmeldestring erstellen
                $params['nonce'] = $sso->get_nonce( $payload );
                $q               = $sso->build_login_string( $params );
            } catch ( \Exception $e ) {
                // Fehler behandeln, wenn es ein Problem bei der Generierung der SSO-Parameter gibt
                return $this->handle_error( 'parse_request.invalid_sso_params', array( 'message' => esc_html( $e->getMessage() ) ) );
            }

            // Eine Aktion auslösen, bevor der Benutzer zur SSO-Anmeldung weitergeleitet wird (nützlich zum Protokollieren)
            do_action( 'wpdc_sso_provider_before_sso_redirect', $current_user->ID, $current_user );

            // Den authentifizierten Benutzer protokollieren, wenn die ausführliche Protokollierung aktiviert ist
            if ( ! empty( $this->options['verbose-sso-logs'] ) ) {
                $this->logger->info( 'parse_request.success', array( 'user_id' => $current_user->ID ) );
            }

            // Den authentifizierten Benutzer zur DiscourseConnect-Anmelde-URL mit dem SSO-Anmeldestring weiterleiten
            return $this->redirect_to( $this->options['url'] . '/session/sso_login?' . $q );
        }
    }

    // Null zurückgeben, wenn keine SSO-Parameter in der Anfrage gefunden werden
    return null;
}

Festlegen des Rückgabepfads auf Nicht-Discourse-URLs

Discourse ermöglicht es Ihnen, einen Benutzer anzumelden und ihn zu einer Nicht-Discourse-URL weiterzuleiten. Beachten Sie, dass Sie hierfür die Domain zu der Site-Einstellung discourse connect allowed redirect domains hinzufügen müssen. Standardmäßig ist diese Einstellung leer – was Weiterleitungen zu Nicht-Discourse-URLs verhindert. Sie können auch * als Platzhalter verwenden, um alle Domains zuzulassen. Wenn Sie dies aktivieren, stellen Sie sicher, dass Sie die absolute URL im return_path-Parameter für alle Nicht-Discourse-URLs verwenden, zu denen Sie Benutzer weiterleiten möchten.

21 „Gefällt mir“

Ich verwende diese Methode, muss mich aber jedes Mal über SSO anmelden.

Wie können wir das nahtlos gestalten, das heißt, wenn ich mich bereits bei Discourse angemeldet habe, muss ich nicht mehr zur SSO-Seite gehen, um mich erneut anzumelden?

1 „Gefällt mir“

Sofern sich nichts geändert hat, ist dies die erwartete Funktionsweise des Links. Wenn Sie beispielsweise bei Discourse angemeldet sind und auf einen Link auf der SSO-Anbieterseite klicken, der auf https://forum.example.com/session/sso?return_path=/t/some-slug/23 verweist, sollten Sie nahtlos zu /t/some-slug/23 weitergeleitet werden, ohne die Anmeldeseite besuchen zu müssen.

1 „Gefällt mir“

Ich bin bereits auf dem neuesten Stand von Discourse und so funktioniert das SSO für mich:

Wie Sie sehen können, bin ich bereits angemeldet, aber wenn ich eine URL wie https://forum.example.com/session/sso?return_path=/t/some-slug/23 eingebe, werde ich erneut zur SSO-Anmeldeseite weitergeleitet.

Ich glaube, was passiert, ist, dass Sie beim Besuch einer Route wie https://forum.example.com/session/sso?return_path=/t/some-slug/23 von Discourse zur discourse connect url weitergeleitet werden, unabhängig davon, ob Sie bei Discourse angemeldet sind oder nicht. Das passiert hier:

Die SSO-Provider-Site soll dann den Fall von Benutzern behandeln, die bereits auf der Website angemeldet sind. Hier ist, wie das WP Discourse-Plugin damit umgeht:

Dieser Code (was nach der else-Anweisung kommt) behandelt den Fall von Benutzern, die bereits bei WordPress angemeldet sind. Sie werden zur URL weitergeleitet, die durch den return_path-Query-Parameter bereitgestellt wird. Aus Sicht des Benutzers werden sie direkt zur Return-Path-URL weitergeleitet, aber was tatsächlich passiert, ist, dass sie zur SSO-Provider-Site und dann zurück zu Discourse weitergeleitet werden.

Ich glaube, das Problem auf Ihrer Website ist, dass Ihr SSO-Code den Fall von Benutzern, die bereits auf der Website angemeldet sind, nicht behandelt.

Ich habe derzeit keine Möglichkeit, dies zu testen. Es ist möglich, dass ich den Code falsch lese. Bevor ich mir den Code angesehen habe, dachte ich, dass auf Discourse-Seite eine Prüfung durchgeführt wird, um festzustellen, ob der Benutzer bereits bei Discourse angemeldet war, aber das scheint nicht der Fall zu sein.

3 „Gefällt mir“

Vielen Dank für Ihre Erklärung.

Ja, das ist etwas, das wir in unserem SSO beheben werden.

Jedoch

Ich denke, diese Prüfung auf Discourse-Seite hätte eine bessere Benutzererfahrung geschaffen.

1 „Gefällt mir“

Ich habe den OP bearbeitet, um Details darüber hinzuzufügen, wie der Prozess funktioniert und wie mit Benutzern umgegangen wird, die auf der SSO-Anbieterseite bereits authentifiziert sind. Diese Frage ist ein paar Mal aufgetaucht.

Möglicherweise könnte eine weniger detaillierte Version dieses Themas in Setup DiscourseConnect - Official Single-Sign-On for Discourse (sso) - #482 integriert werden. Der return_path-Query-Parameter wird in diesem Thema nicht erwähnt.