Especificación de claves API de usuario

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 Me gusta

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

6 Me gusta

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 Me gusta

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?

Hola… no sé cómo generar la public_key. ¿Debería usar un generador de RSA para obtener la clave pública/privada?
Si es así, ya he usado algunos generadores de RSA en línea, pero obtengo este error:

OpenSSL::PKey::RSAError (Ni clave PUB ni PRIV: error asn1 anidado) /var/www/discourse/app/controllers/user_api_keys_controller.rb:189:in `initialize'

También quiero preguntarles si esto se ajusta a mi caso de uso:
Tengo una aplicación y básicamente quiero autenticar al usuario y obtener el nombre de usuario. ¿Es el flujo de generación de claves API el más sencillo para validar el inicio de sesión del usuario en mi aplicación? Si es posible, quiero evitar SSO porque parece más complicado.

Yo también estoy en la misma situación, aunque solo estoy intentando usar User-Api-Key (no Api-Key) para crear una publicación en un tema y estoy recibiendo una denegación CSRF por parte de la biblioteca actionpack.

A menos que el servidor de Discourse haya desactivado la verificación CSRF, publicar desde una aplicación de escritorio de terceros parece difícil. No voy a emular un navegador.

@sam ¿Qué opinas sobre permitir que las claves de API de usuario que solo tienen el alcance read se pasen mediante parámetros de URL en las solicitudes GET?

El caso de uso es permitir integraciones como suscribir tus Marcadores mejorados con recordatorios en Google Calendar usando claves de API de usuario.

5 Me gusta

¿Qué tal si creamos un nuevo ámbito específico, con un tercer parámetro para indicar ‘parámetro de consulta permitido’? De esta manera, la gente no podrá abusar de él para otros fines (por ejemplo, eludir CORS y solicitar la API de Discourse desde otro sitio).

(desde aquí)

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

(A parte: ¿por qué estamos usando arrays anidados aquí…)

10 Me gusta

Me gusta que la clave de API se marque explícitamente como «permitida en GET» a nivel de usuario.

En general, la opción podría estar abierta para cualquier solicitud GET. La regla que me gusta es que, al operar en este modo:

  1. La clave de API del usuario esté 100% restringida a una única acción de controlador GET específica.
  2. La clave de API del usuario se marque como permitida en los parámetros de consulta GET.

Esto limita el impacto de cualquier fuga aquí a través de un proxy, ya que la clave nunca se reutilizará.

Supongo que {get: 'list#new'}, {get: 'list#latest'} también funcionaría.

7 Me gusta

Estoy muy interesado en las claves de API de usuario del tipo get param only. Mi pregunta es: ¿tienen previsto permitir que los usuarios generen estas claves a través de la interfaz gráfica?

Probablemente, quizás detrás de una configuración del sitio o con un complemento. Tenemos previsto normalizar un poco el conjunto de funciones para que las claves de API de administración también admitan ámbitos.

4 Me gusta

Hola… ¿Puedes resolver este problema? Tengo el mismo problema y no puedo solucionarlo. Probé pasando diferentes tipos de claves y nada funcionó. Cualquier ayuda sería muy apreciada.

¿Hay alguna biblioteca para esto? Si no, ¿alguna implementación de ejemplo? Estoy intentando usar PHP para identificar la cuenta de Discourse de un usuario en una parte separada del sitio web. Esto parece un flujo de OAuth modificado, pero estoy un poco confundido sobre cómo implementarlo.

Específicamente, no estoy seguro de cómo hacer toda la generación de claves pública/privada.

¿Hay alguna manera de usar simplemente OAuth 2 con Discourse como proveedor de OAuth?

2 Me gusta

¿Lo lograste usando la User-Api-Key? Yo también estoy recibiendo el mensaje «You are not permitted to view the requested resource».

1 me gusta

He descubierto qué hice mal: la carga útil devuelta no es la clave de la API de UserAPI en sí, sino una cadena JSON cifrada que debe descifrarse con la clave privada del par de claves pública/privada.

2 Me gusta

EDIT: He logrado que la mayor parte funcione y proporcionaré una descripción una vez que esté completamente operativo.


¿Cómo obtiene el cliente el par de claves privada/pública y el ID?

¿Podrías proporcionar código para obtener la clave de API de usuario con una aplicación de JavaScript? (Una aplicación de JavaScript que intenta permitir a un usuario realizar llamadas a la API de un foro de Discourse).

Estoy recibiendo errores 403. O, un error que dice: Lo sentimos, no podemos emitir claves de API de usuario; esta función puede estar deshabilitada por el administrador del sitio (aunque mi sitio ha marcado: Permitir la generación de claves de API de usuario).

Creo que el problema podría ser cómo generar el par de claves privada/pública (¿cómo se hace eso?) y luego manejar la redirección.

Agradezco cualquier código.

Lo he logrado hacer funcionar, tras varios intentos y errores.

Estos son los pasos básicos que sigo cuando tengo una aplicación independiente que he programado y quiero que los usuarios puedan usarla para realizar llamadas a la API de un sitio de Discourse.

Para ello, necesito generar un token de API por usuario para realizar llamadas en nombre de cada usuario específico (al menos en un entorno de Node.js/JavaScript).


Tenga en cuenta que, para la parte de JavaScript, encontré que el código proporcionado por @KengoTODA aquí: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub fue de gran ayuda.


Estos son los pasos que he seguido:

Primero: Generar un par de claves pública y privada.

Esto es algo que su aplicación debe generar: una clave pública y una privada. El gist de GitHub proporciona un método para hacerlo.

Segundo: Tener una URL de redirección.

Esta es la URL a la que Discourse redirigirá, proporcionando el token de API final en la carga útil (payload). Si tiene una aplicación de escritorio (es decir, no tiene una URL de navegador), la URL de redirección se basará en un protocolo personalizado que configure para abrir la aplicación cuando se ingrese la URL de redirección en el navegador.

Tenga en cuenta que la URL de redirección debe estar en la lista blanca en la configuración del sitio del sitio de Discourse de destino.

El sitio de Discourse también probablemente necesite tener activada la configuración del sitio para “Permitir claves de API de usuario”. Consulte la publicación original sobre este tema para obtener detalles sobre “Configuración del sitio”.

Tercero: Enviar la llamada de solicitud de API a la URL de solicitud de Discourse.

Su aplicación enviará una llamada a una URL que sigue este formato:

https://[su sitio de Discourse de destino .com]/user-api-key-new"

y agregando como parámetros:

  • el nombre de su aplicación
  • su “client_id” (pude usar hostname(), desde const {hostname} = require('os') para una aplicación de escritorio, al igual que en el gist de GitHub mencionado anteriormente)
  • ámbitos (scopes) (estos son los ámbitos que desea que el usuario pueda utilizar a través de la API, como “write”, “read”, etc.)
  • su clave pública (del paso 1 anterior)
  • su URL de redirección (del paso 2 anterior)
  • nonce (este es un valor que puede elegir; por ejemplo, usar simplemente ‘1’ parece funcionar)

Cuarto: El usuario autoriza su aplicación en la página del sitio de Discourse que se abre mediante la URL de solicitud

Cuando envíe la URL de solicitud correctamente, se abrirá una página en el sitio de Discourse informando al usuario que su aplicación desea acceder al sitio.

En esa página, hay un botón para que el usuario permita esto. Cuando el usuario hace clic en este botón, el sitio de Discourse redirige a la URL de redirección que proporcionó y adjunta como parámetro un ?payload=[LA CLAVE DE API]. La CLAVE DE API aquí es la clave que necesita decodificar en su aplicación.

Quinto: Su aplicación captura el valor de la URL de redirección (con el valor de carga útil) y decodifica la CLAVE DE API

Casi ha terminado. Su aplicación debe analizar la URL de redirección a la que fue Discourse y obtener la clave de API contenida en la carga útil.

Una vez que tenga esa clave de API, debe hacer dos cosas:

  1. Obtener la clave real, no la versión codificada en URL: si está obteniendo un parámetro de una URL, a menudo está codificada en URL (agregando % aquí y allá, etc.). Necesita limpiarla. En JavaScript, he encontrado que decodeURIComponent funciona para esto.
  2. Una vez que tenga la CLAVE DE API limpiada devuelta por Discourse, debe decodificarla. Para ello, puede usar la decodificación de JavaScript con claves privadas. Básicamente, usa su clave privada (generada en el primer paso anterior) para decodificar la CLAVE DE API limpiada. Hay algún ejemplo de JavaScript en el gist de GitHub que mencioné anteriormente: discourse-api-key-generator/src/index.ts at main · KengoTODA/discourse-api-key-generator · GitHub

Después de ejecutar su código de decodificación, tiene el token en sí, que ahora puede usar para realizar llamadas de API autenticadas en nombre del usuario.

Sexto: Usar el token (es decir, la clave de API final, limpiada y decodificada) para realizar llamadas a la API en nombre del usuario

Con ese token, parece que no necesita ingresar el nombre de usuario en la llamada a la API. Encuentro que la siguiente cabecera es suficiente cuando la incluye en su llamada GET, POST, PUT, etc.:

headers: {
"User-Api-Key": [el token]
}

Y con eso, espero que tenga un método de autenticación por usuario funcional para interactuar con Discourse.

7 Me gusta

¿Cuáles son las implicaciones de seguridad de agregar elementos a allowed_user_api_auth_redirects? Tengo a alguien pidiendo agregar una cadena para admitir la integración con NextCloud.

1 me gusta