Spezifikation der User API Keys

I find allowed_user_api_auth_redirects default of “discourse://auth_redirect” rather restrictive, especially because “discourse” does not appear to be a valid URI scheme.

Please explain the thinking behind this default. Thank you.

I am having this issue as well. If I initiate the API from a JS application, then automatically the allowed headers are: User-Api-Key, User-Api-Client-Id even though I do not need user API keys. All I want is a simple API key but I cannot get anything to work. If I try to pass Api-Key in the headers I get a CORS error since it expects User-Api-Key. But when I try to use User-Api-Key, I get 403 errors. I am stuck. I would think this is the base usage for using the APIs. I am not trying to do anything out of the ordinary. I am simply trying to create a new topic post.

2 „Gefällt mir“

That is the custom URI scheme used by the DiscourseHub app for iOS and Android.

6 „Gefällt mir“

I’ve got a question concerning the “read tokens” and “write tokens”. This comment here is from 2016, so this possibly had already been changed? Or are the defaults still only “read tokens”?

Background: I’m one of the coders behind a distributed social media system. We already do have connectors to non-federating systems. The idea is to write an addon for discourse as well. But when most likely most system won’t allow users to generate tokens that allow posting, we will try another way. We already do have a mail connector. Then we will simply use the mailing list function of Discourse and we will try to enhance the returned content and will post via SMTP.

You can do write tokens if you ask for the scope upfront

3 „Gefällt mir“

Of course this is always possible. But I have the feeling that this is a support nightmare. Our software has got some hundred installations with (in total) more than 10k users. When they see that there is an addon that is connection to Discourse, many will surely like to use it. And since it most likely won’t work out of the box, this will generate questions and support work from our side. Additionally it will generate work for the admins of the several Discourse installations. And very likely not all will allow it - which will cause frustration.

So possibly at first I will focus on integrating the mailing list mode mails. Or is it possible to combine these two? Means: Reading of the posts via the API, but posting via SMTP?

Hallo… ich weiß nicht, wie ich einen public_key generieren soll. Soll ich einen RSA-Generator verwenden, um ein öffentliches/privates Schlüsselpaar zu erhalten?
Falls ja, habe ich einige Online-RSA-Generatoren ausprobiert, aber ich erhalte folgenden Fehler:

OpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: nested asn1 error) /var/www/discourse/app/controllers/user_api_keys_controller.rb:189:in `initialize'

Außerdem möchte ich euch fragen, ob dies für meinen Anwendungsfall geeignet ist:
Ich habe eine App und möchte im Grunde Benutzer authentifizieren und den Benutzernamen abrufen. Ist der Ablauf zur Generierung eines API-Schlüssels der einfachste Weg, um die Anmeldung des Benutzers in meiner App zu validieren? Wenn möglich, möchte ich SSO vermeiden, da dies komplizierter erscheint.

Bei mir ist es ähnlich, auch wenn ich versuche, nur den User-Api-Key (nicht Api-Key) zu verwenden, um einen Themenbeitrag zu erstellen, erhalte ich eine CSRF-Ablehnung aus der actionpack-Bibliothek.

Es sei denn, der Discourse-Server hat die CSRF-Prüfung deaktiviert, scheint das Posten von einer Drittanbieter-Desktop-App schwierig zu sein. Ich werde keinen Browser emulieren.

@sam Was hältst du davon, User-API-Schlüssel mit dem Scope read in URL-Parametern bei GET-Anfragen zu erlauben?

Der Anwendungsfall ist die Unterstützung von Integrationen wie dem Abonnieren deines Improved Bookmarks with Reminders in Google Calendar mit User-API-Schlüsseln.

5 „Gefällt mir“

Wie wäre es damit, einen spezifischen neuen Scope mit einem dritten Parameter zu erstellen, der angibt, ob ein GET-Parameter erlaubt ist. Auf diese Weise kann er nicht für andere Zwecke missbraucht werden (z. B. zum Umgehen von CORS und zum Anfordern der Discourse-API von einer anderen Website).

(Quelle)

SCOPES = {
    read: [:get],
    write: [:get, :post, :patch, :put, :delete],
    message_bus: [[:post, 'message_bus']],
    push: nil,
    one_time_password: nil,
    notifications: [[:post, 'message_bus'], [:get, 'notifications#index'], [:put, 'notifications#mark_read']],
    session_info: [
      [:get, 'session#current'],
      [:get, 'users#topic_tracking_state'],
      [:get, 'list#unread'],
      [:get, 'list#new'],
      [:get, 'list#latest']
    ],
+   calendar: [ [:get, 'users#bookmarks_cal', true ] ],
  }

(Nebenbemerkung: Warum verwenden wir hier verschachtelte Arrays…)

10 „Gefällt mir“

Es gefällt mir, dass der API-Schlüssel auf Benutzerebene explizit als „in GET erlaubt

7 „Gefällt mir“

Ich bin super interessiert an API-Schlüsseln vom Typ „get param only“. Meine Frage ist: Plant ihr, dass Nutzer diese Schlüssel über die Benutzeroberfläche generieren können?

Wahrscheinlich, eventuell hinter einer Site-Einstellung oder mit einem Plugin. Wir planen, den Funktionsumfang etwas zu vereinheitlichen, sodass Admin-API-Schlüssel auch Berechtigungsbereiche unterstützen.

4 „Gefällt mir“

Hallo… Können Sie dieses Problem lösen? Ich habe das gleiche Problem und kann es nicht beheben. Ich habe versucht, verschiedene Arten von Schlüsseln zu übergeben, aber nichts hat funktioniert. Jegliche Hilfe wäre sehr willkommen.

Gibt es dafür Bibliotheken? Falls nicht, gibt es ein Beispiel für eine Implementierung? Ich versuche, mit PHP das Discourse-Konto eines Benutzers in einem anderen Bereich der Website zu identifizieren. Das scheint ein modifizierter OAuth-Flow zu sein, aber ich bin mir bei der Umsetzung etwas unsicher.

Insbesondere bin ich mir nicht sicher, wie man die gesamte Generierung von öffentlichen und privaten Schlüsseln durchführt.

Gibt es eine Möglichkeit, einfach OAuth 2 mit Discourse als OAuth-Anbieter zu verwenden?

2 „Gefällt mir“

Hast du das mit dem User-Api-Key geschafft? Ich erhalte ebenfalls die Meldung „Sie sind nicht berechtigt, die angeforderte Ressource anzuzeigen“.

1 „Gefällt mir“

Ich habe herausgefunden, was ich falsch gemacht habe: Das zurückgegebene Payload ist nicht der UserAPI-Schlüssel selbst, sondern ein verschlüsselter JSON-String, der mit dem privaten Schlüssel des privaten/öffentlichen Schlüsselpaares entschlüsselt werden müsste.

2 „Gefällt mir“

EDIT: Ich habe es größtenteils zum Laufen gebracht und werde eine Beschreibung liefern, sobald alles vollständig funktioniert.


Wie erhält der Client das private/öffentliche Schlüsselpaar und die ID?

Können Sie Code für das Abrufen des User-API-Schlüssels mit einer JavaScript-App bereitstellen? (Eine JavaScript-App, die einem Benutzer ermöglichen soll, API-Aufrufe an ein Discourse-Forum durchzuführen).

Ich erhalte 403-Fehler. Oder eine Fehlermeldung: Entschuldigung, wir können keine User-API-Schlüssel ausstellen. Diese Funktion wurde möglicherweise vom Site-Administrator deaktiviert (obwohl auf meiner Site die Option Zulassen der Generierung von User-API-Schlüsseln aktiviert ist).

Ich denke, das Problem könnte darin bestehen, wie das private/öffentliche Schlüsselpaar generiert wird (wie wird das gemacht?) und wie die Weiterleitung behandelt wird.

Jeder Code wird geschätzt.

Ich habe es nach einigen Versuchen und Fehlern zum Laufen gebracht.

Hier sind die grundlegenden Schritte, die ich befolge, wenn ich eine separate App habe, die ich programmiert habe, und ich möchte, dass Benutzer diese App nutzen können, um API-Aufrufe an eine Discourse-Seite zu tätigen.

Dafür muss ich ein pro-Benutzer-API-Token generieren, um im Namen jedes spezifischen Benutzers Aufrufe zu tätigen (zumindest in einer Node.js/JavaScript-Umgebung).


Hinweis: Für den JavaScript-Teil habe ich den Code, den @KengoTODA hier bereitgestellt hat, als sehr hilfreich erachtet: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub


Hier sind die Schritte, die ich befolgt habe:

Erstens: Ein Schlüsselpaar aus öffentlicher und privater Schlüssel generieren.

Dies ist etwas, das Ihre App generieren muss – einen öffentlichen und einen privaten Schlüssel. Der GitHub-Gist bietet eine Methode dafür an.

Zweitens: Eine Redirect-URL bereitstellen.

Dies ist die URL, zu der Discourse weiterleitet und das finale API-Token im Payload bereitstellt. Wenn Sie eine Desktop-App haben (also eine ohne Browser-URL), basiert die Redirect-URL auf einem benutzerdefinierten Protokoll, das Sie eingerichtet haben und das die App öffnet, wenn die Redirect-URL im Browser eingegeben wird.

Beachten Sie, dass die Redirect-URL in den Site-Einstellungen der Ziel-Discourse-Seite freigegeben (whitelisted) sein muss.

Die Discourse-Seite muss zudem wahrscheinlich die Einstellung „Benutzer-API-Schlüssel zulassen" aktiviert haben. Weitere Informationen dazu finden Sie im Originalbeitrag zu diesem Thema unter „Site Settings".

Drittens: Den API-Anfrageaufruf an die Discourse-Request-URL senden.

Ihre App sendet also einen Aufruf an eine URL, die dieses Format hat:

https://[ihre Ziel-Discourse-Seite .com]/user-api-key-new

und folgende Parameter hinzufügt:

  • Ihr App-Name
  • Ihre „client_id" (Ich konnte für eine Desktop-App hostname() aus const {hostname} = require('os') verwenden, genau wie im oben genannten GitHub-Gist)
  • Scopes (dies sind die Berechtigungen, die der Benutzer über die API ausführen können soll, z. B. „write", „read" usw.)
  • Ihren öffentlichen Schlüssel (aus Schritt 1 oben)
  • Ihre Redirect-URL (aus Schritt 2 oben)
  • Nonce (dies ist ein Wert, den Sie wählen können – beispielsweise scheint die Verwendung von „1" zu funktionieren)

Viertens: Der Benutzer autorisiert Ihre App auf der Discourse-Seite, die durch die Request-URL geöffnet wird.

Wenn Sie die Request-URL erfolgreich senden, öffnet sich eine Seite auf der Discourse-Seite, die dem Benutzer mitteilt, dass Ihre App Zugriff auf die Seite möchte.

Auf dieser Seite befindet sich eine Schaltfläche, mit der der Benutzer dies zulassen kann. Wenn der Benutzer auf diese Schaltfläche klickt, leitet Discourse zur bereitgestellten Redirect-URL weiter und hängt als Parameter ?payload=[DER API-SCHLÜSSEL] an. Der API-SCHLÜSSEL hier ist der Schlüssel, den Sie in Ihrer App entschlüsseln müssen.

Fünftens: Ihre App nimmt den Redirect-URL-Wert (mit Payload-Wert) auf, und Sie entschlüsseln den API-SCHLÜSSEL.

Sie sind fast am Ziel. Ihre App muss die Redirect-URL, zu der Discourse weitergeleitet hat, analysieren und den darin enthaltenen API-Schlüssel aus dem Payload extrahieren.

Sobald Sie diesen API-Schlüssel haben, müssen Sie zwei Dinge tun:

  1. Den tatsächlichen Schlüssel erhalten, nicht die URL-kodierte Version: Wenn Sie einen Parameter aus einer URL erhalten, ist dieser oft URL-kodiert (mit % hier und dort usw.). Sie müssen ihn bereinigen. In JavaScript habe ich festgestellt, dass decodeURIComponent dafür funktioniert.
  2. Sobald Sie den bereinigten API-SCHLÜSSEL von Discourse erhalten haben, müssen Sie ihn entschlüsseln. Dafür können Sie die JavaScript-Entschlüsselung mit privaten Schlüsseln verwenden. Im Wesentlichen verwenden Sie Ihren privaten Schlüssel (im ersten Schritt oben generiert), um den bereinigten API-SCHLÜSSEL zu entschlüsseln. Es gibt einige Beispiel-Code-Schnipsel in JavaScript im oben genannten GitHub-Gist: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub

Nachdem Sie Ihren Entschlüsselungscode ausgeführt haben, haben Sie das Token selbst, das Sie nun verwenden können, um im Namen des Benutzers authentifizierte API-Aufrufe zu tätigen.

Sechstens: Verwenden Sie das Token (d. h. den finalen, bereinigten, entschlüsselten API-SCHLÜSSEL), um API-Aufrufe im Namen des Benutzers zu tätigen.

Mit diesem Token scheint es nicht erforderlich zu sein, den Benutzernamen im API-Aufruf anzugeben. Ich finde, dass folgender Header ausreicht, wenn Sie ihn in Ihren GET-, POST-, PUT- usw. Aufrufen einfügen:

headers: {
"User-Api-Key": [das Token]
}

Und damit haben Sie hoffentlich eine funktionierende pro-Benutzer-Authentifizierungsmethode, um mit Discourse zu interagieren.

7 „Gefällt mir“

Welche Sicherheitsauswirkungen hat das Hinzufügen von Dingen zu allowed_user_api_auth_redirects? Jemand bittet darum, einen String hinzuzufügen, um die NextCloud-Integration zu unterstützen.

1 „Gefällt mir“