Spécification des clés API utilisateur

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 « J'aime »

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

6 « J'aime »

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 « J'aime »

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?

Hi…I don’t know to generate public_key… should I use RSA generator to get public/private key?
If so I have done with some online RSA generators. but I am getting this error:

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'

Also, I want to ask you guys if this suits my user case:
I have an app, and I want to basically authenticate user and get the username, is generating api key flow the simplest flow for me to validate user’s login in my app? If possible, I want avoid SSO because it seems more complicate.

Same boat here, although I am only trying to use User-Api-Key (not Api-Key) to create a topic post and am getting CSRF denial from the actionpack library.

Unless the discourse server has turned off CSRF checking, posting from a third-party desktop app seems hard. I’m not about to emulate a browser.

@sam Quelle est ton opinion sur le fait d’autoriser les clés API utilisateur qui n’ont que la portée read attachée, à être transmises via des paramètres d’URL sur les requêtes GET ?

Le cas d’usage consiste à permettre des intégrations comme la souscription à Improved Bookmarks with Reminders dans Google Calendar en utilisant des clés API utilisateur.

5 « J'aime »

Et si on créait une nouvelle portée spécifique, avec un troisième paramètre pour indiquer « paramètre GET autorisé ». De cette façon, les utilisateurs ne pourront pas l’utiliser à d’autres fins (par exemple, contourner CORS et interroger l’API Discourse depuis un autre site).

(à partir d’ici)

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 ] ],
  }

(Au passage : pourquoi utilisons-nous des tableaux imbriqués ici…)

10 « J'aime »

J’aime que la clé API soit explicitement signalée comme « autorisée en GET » au niveau de l’utilisateur.

Dans l’ensemble, l’option pourrait être ouverte à toutes les requêtes GET. La règle que je privilégie, lors du fonctionnement dans ce mode, est la suivante :

  1. La clé API de l’utilisateur est strictement limitée à une seule action de contrôleur GET spécifique.
  2. La clé API de l’utilisateur est signalée comme autorisée dans les paramètres de requête GET.

Cela limite l’impact de toute fuite ici via un proxy, car la clé ne sera jamais réutilisée.

Je suppose que {get: 'list#new'}, {get: 'list#latest'} fonctionnerait également.

7 « J'aime »

Je suis super intéressé par les clés d’API utilisateur de type « get param only ». Ma question est : avez-vous prévu de permettre aux utilisateurs de générer ces clés via l’interface utilisateur ?

Probablement, peut-être via un paramètre du site ou avec un plugin. Nous prévoyons de normaliser un peu l’ensemble des fonctionnalités afin que les clés d’API d’administration prennent également en charge les scopes.

4 « J'aime »

Bonjour… Êtes-vous en mesure de résoudre ce problème ? Je rencontre le même problème et je n’arrive pas à le corriger. J’ai essayé de transmettre différents types de clés, mais rien n’a fonctionné. Toute aide serait grandement appréciée.

Y a-t-il des bibliothèques pour cela ? Sinon, une implémentation d’exemple ? J’essaie d’utiliser PHP pour identifier le compte Discourse d’un utilisateur sur une autre partie du site. Cela ressemble à un flux OAuth modifié, mais je suis un peu confus quant à la manière de l’implémenter.

Plus précisément, je ne suis pas sûr de savoir comment procéder à toute la génération de clés publique/privée.

Existe-t-il un moyen d’utiliser simplement OAuth 2 avec Discourse en tant que fournisseur OAuth ?

2 « J'aime »

Avez-vous réussi cela en utilisant la User-Api-Key ? J’obtiens également le message « Vous n’êtes pas autorisé à afficher la ressource demandée ».

1 « J'aime »

J’ai compris ce que j’ai fait de mal : la charge utile renvoyée n’est pas la clé de l’API UserAPI elle-même, mais une chaîne JSON chiffrée qu’il faudrait déchiffrer à l’aide de la clé privée de la paire de clés publique/privée.

2 « J'aime »

MODIF : J’ai réussi à faire fonctionner la majeure partie du processus et je fournirai une description une fois que tout sera entièrement opérationnel.


Comment le client obtient-il la paire de clés privée/publique et l’identifiant ?

Pouvez-vous fournir du code pour obtenir la clé API utilisateur avec une application JavaScript ? (Une application JavaScript tentant de permettre à un utilisateur d’effectuer des appels API vers un forum Discourse).

Je rencontre des erreurs 403. Ou une erreur indiquant : Désolé, nous ne pouvons pas émettre de clés API utilisateur, cette fonctionnalité peut être désactivée par l'administrateur du site (même si mon site a coché : Autoriser la génération de clés API utilisateur).

Je pense que le problème pourrait venir de la façon de générer la paire de clés privée/publique (comment cela se fait-il ?), puis de gérer la redirection.

Tout code est apprécié.

J’ai réussi à faire fonctionner cela, après quelques essais et erreurs.

Voici les étapes de base que je suis lorsque j’ai une application distincte que j’ai codée et que je souhaite que les utilisateurs puissent l’utiliser pour effectuer des appels API vers un site Discourse.

Pour ce faire, je dois générer un jeton API par utilisateur afin d’effectuer des appels au nom de chaque utilisateur spécifique (du moins dans un environnement Node.js/JavaScript).


Notez que pour la partie JavaScript, j’ai trouvé le code fourni par @KengoTODA ici très utile : discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub


Voici les étapes que j’ai suivies :

Premièrement : Générer une paire de clés publique et privée.

C’est quelque chose que votre application doit générer : une clé publique et une clé privée. Le Gist GitHub fournit une méthode pour y parvenir.

Deuxièmement : Avoir une URL de redirection.

C’est l’URL vers laquelle Discourse redirigera, en fournissant le jeton API final dans la charge utile. Si vous avez une application de bureau (c’est-à-dire sans URL de navigateur), l’URL de redirection sera basée sur un protocole personnalisé que vous avez configuré et qui ouvre l’application lorsque l’URL de redirection est saisie dans le navigateur.

Notez que l’URL de redirection doit être ajoutée à la liste blanche dans les paramètres du site du site Discourse cible.

Le site Discourse doit également probablement avoir l’option « Autoriser les clés API utilisateur » cochée dans ses paramètres. Consultez le message original sur ce sujet pour les « Paramètres du site ».

Troisièmement : Envoyer l’appel de requête API à l’URL de requête de Discourse.

Votre application enverra donc un appel à une URL qui suit ce format :

https://[votre site Discourse cible .com]/user-api-key-new

en ajoutant les paramètres suivants :

  • le nom de votre application
  • votre « client_id » (j’ai pu utiliser hostname(), depuis const {hostname} = require('os') pour une application de bureau, tout comme dans le Gist GitHub référencé ci-dessus)
  • les portées (scopes) (ce sont les actions que vous souhaitez que l’utilisateur puisse effectuer via l’API, comme « write », « read », etc.)
  • votre clé publique (de l’étape 1 ci-dessus)
  • votre URL de redirection (de l’étape 2 ci-dessus)
  • nonce (c’est une valeur que vous pouvez choisir – par exemple, utiliser simplement ‘1’ semble fonctionner)

Quatrièmement : L’utilisateur autorise votre application sur la page du site Discourse ouverte par l’URL de requête

Lorsque vous envoyez l’URL de requête avec succès, une page s’ouvre sur le site Discourse indiquant à l’utilisateur que votre application souhaite accéder au site.

Sur cette page, il y a un bouton permettant à l’utilisateur d’autoriser cette action. Lorsque l’utilisateur clique sur ce bouton, le site Discourse redirige vers l’URL de redirection que vous avez fournie et attache en paramètre un ?payload=[LA CLÉ API]. La CLÉ API ici est la clé que vous devez décoder dans votre application.

Cinquièmement : Votre application récupère la valeur de l’URL de redirection (avec la valeur de la charge utile), et vous décodez la CLÉ API

Vous y êtes presque. Votre application doit analyser l’URL de redirection vers laquelle Discourse a redirigé et récupérer la clé API contenue dans la charge utile.

Une fois que vous avez cette clé API, vous devez faire deux choses :

  1. Obtenir la clé réelle, et non la version encodée en URL : si vous récupérez un paramètre depuis une URL, il est souvent encodé en URL (ajout de % ici et là, etc.). Vous devez le nettoyer. En JavaScript, j’ai trouvé que decodeURIComponent fonctionne pour cela.
  2. Une fois que vous avez la CLÉ API nettoyée renvoyée par Discourse, vous devez la décoder. Pour ce faire, vous pouvez utiliser le décodage JavaScript avec des clés privées. Fondamentalement, vous utilisez votre clé privée (générée à la première étape ci-dessus) pour décoder la CLÉ API nettoyée. Il existe un exemple de code JavaScript dans le Gist GitHub que j’ai référencé ci-dessus : discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub

Après avoir exécuté votre code de décodage, vous obtenez le jeton lui-même, que vous pouvez maintenant utiliser pour effectuer des appels API authentifiés au nom de l’utilisateur.

Sixièmement : Utiliser le jeton (c’est-à-dire la CLÉ API finale, nettoyée et décodée) pour effectuer des appels API au nom de l’utilisateur

Avec ce jeton, il semble que vous n’ayez pas besoin de saisir le nom d’utilisateur dans l’appel API. Je trouve que l’en-tête suivant est suffisant lorsque vous l’incluez dans vos appels GET, POST, PUT, etc. :

headers: {
"User-Api-Key": [le jeton]
}

Et avec cela, vous avez hopefully une méthode d’authentification par utilisateur fonctionnelle pour interagir avec Discourse.

7 « J'aime »

Quelles sont les implications en matière de sécurité de l’ajout d’éléments à allowed_user_api_auth_redirects ? Quelqu’un demande l’ajout d’une chaîne de caractères pour prendre en charge l’intégration NextCloud.

1 « J'aime »