Spécification des clés API utilisateur

Je trouve que la valeur par défaut de allowed_user_api_auth_redirects, soit “discourse://auth_redirect”, est plutôt restrictive, d’autant plus que “discourse” ne semble pas être un schéma d’URI valide.

Pourriez-vous m’expliquer la logique derrière cette valeur par défaut ? Merci.

Je rencontre le même problème. Si j’initialise l’API depuis une application JS, les en-têtes autorisés sont automatiquement : User-Api-Key et User-Api-Client-Id, même si je n’ai pas besoin de clés API utilisateur. Tout ce que je souhaite, c’est une simple clé API, mais rien ne fonctionne. Lorsque j’essaie de passer Api-Key dans les en-têtes, je reçois une erreur CORS car l’API attend User-Api-Key. Mais quand j’essaie d’utiliser User-Api-Key, je reçois des erreurs 403. Je suis bloqué. Je pensais que c’était l’utilisation de base des API. Je ne tente rien d’extraordinaire. J’essaie simplement de créer un nouveau sujet.

2 « J'aime »

C’est le schéma d’URI personnalisé utilisé par l’application DiscourseHub pour iOS et Android.

6 « J'aime »

J’ai une question concernant les « jetons de lecture » et les « jetons d’écriture ». Ce commentaire date de 2016, il est donc possible que cela ait déjà été modifié ? Ou les valeurs par défaut sont-elles toujours uniquement les « jetons de lecture » ?

Contexte : Je suis l’un des développeurs d’un système de médias sociaux distribué. Nous avons déjà des connecteurs vers des systèmes non fédérés. L’idée est également de créer un module complémentaire pour Discourse. Mais comme la plupart des systèmes n’autoriseront probablement pas les utilisateurs à générer des jetons permettant de publier, nous essaierons une autre approche. Nous avons déjà un connecteur de messagerie. Nous utiliserons simplement la fonction de liste de diffusion de Discourse, nous essaierons d’enrichir le contenu renvoyé et nous publierons via SMTP.

Vous pouvez écrire des jetons si vous demandez la portée dès le départ

3 « J'aime »

Bien sûr, cela est toujours possible. Mais j’ai le sentiment que cela pourrait devenir un cauchemar en termes de support. Notre logiciel compte plusieurs centaines d’installations avec, au total, plus de 10 000 utilisateurs. Lorsqu’ils verront qu’il existe un complément permettant de se connecter à Discourse, beaucoup voudront sûrement l’utiliser. Et comme il est fort probable qu’il ne fonctionnera pas immédiatement, cela générera des questions et du travail de support de notre côté. De plus, cela créera du travail pour les administrateurs des différentes installations Discourse. Et très probablement, tous ne l’autoriseront pas, ce qui entraînera de la frustration.

Donc, peut-être que dans un premier temps, je me concentrerai sur l’intégration des courriels du mode liste de diffusion. Ou est-il possible de combiner ces deux approches ? Je veux dire : lire les publications via l’API, mais publier via SMTP ?

Bonjour… Je ne sais pas comment générer une public_key. Dois-je utiliser un générateur RSA pour obtenir une clé publique/privée ?
Si oui, j’ai utilisé quelques générateurs RSA en ligne, mais je rencontre cette erreur :

OpenSSL::PKey::RSAError (Ni clé PUB ni clé PRIV : erreur asn1 imbriquée) /var/www/discourse/app/controllers/user_api_keys_controller.rb:189:in `initialize'

Je voudrais aussi vous demander si cela convient à mon cas d’usage :
J’ai une application et je souhaite essentiellement authentifier l’utilisateur et récupérer son nom d’utilisateur. Le flux de génération de clé API est-il le plus simple pour moi afin de valider la connexion de l’utilisateur dans mon application ? Si possible, je voudrais éviter le SSO car cela semble plus compliqué.

Même situation de mon côté, bien que j’essaie uniquement d’utiliser User-Api-Key (et non Api-Key) pour créer un sujet, et je reçois un refus CSRF de la part de la bibliothèque actionpack.

À moins que le serveur Discourse n’ait désactivé la vérification CSRF, poster depuis une application de bureau tierce semble difficile. Je ne vais pas émuler un navigateur.

@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 »