Specifiche delle chiavi API utente

Discourse contiene un sistema per la generazione di chiavi API per utente se si segue un protocollo molto specifico. Questa funzionalità facilita l’accesso tramite “applicazione” alle istanze di Discourse senza dover coinvolgere i moderatori.

Descrizione di alto livello

A un alto livello:

  1. Il client (app desktop, plugin browser, app mobile) genera una coppia di chiavi privata/pubblica e un URL di ritorno.

  2. Il client reindirizza a una rotta su Discourse fornendo a Discourse la sua chiave pubblica.

  3. Discourse ottiene l’approvazione dall’utente per utilizzare l’app.

  4. Discourse genera una chiave API utente.

  5. Discourse reindirizza all’URL di ritorno con un payload crittografato utilizzando la chiave pubblica contenente la chiave API utente.

Dettagli

Casi d’uso:

  1. Applicazioni desktop che interrogano i siti Discourse per conto degli utenti finali per ottenere i conteggi delle notifiche su più siti.

  2. Applicazioni mobili che interrogano i siti Discourse per conto degli utenti finali e gestiscono le notifiche push.

  3. Applicazioni web che forniscono una dashboard per gli utenti finali su vari siti Discourse.

  4. Integrazioni personalizzate con app di terze parti che consumano Discourse come parte di un’app aziendale generale. Es: integrare le notifiche della community di Discourse nell’app hopscotch.

La progettazione:

Impostazioni del sito

  • allow_user_api_key_scopes: ambiti di accesso consentiti per le chiavi API utente. Gli ambiti sono definiti qui. Gli ambiti predefiniti disponibili sono: read, write, message_bus, push, one_time_password, notifications, session_info, bookmarks_calendar, user_status (i plugin possono registrare ambiti aggiuntivi).

  • user_api_key_allowed_groups: controlla quali gruppi sono autorizzati a generare chiavi API utente (per impostazione predefinita amministratori, moderatori e trust_level_0)

  • allowed_user_api_push_urls: elenco di siti che possono essere destinazioni per le notifiche push.

  • allowed_user_api_auth_redirects: destinazioni di reindirizzamento consentite dopo la generazione della chiave API utente.

Impostazioni globali

  • max_user_api_reqs_per_minute: 20
  • max_user_api_reqs_per_day: 2880

Elementi UX

Se sono state concesse chiavi API utente, Discourse visualizza una scheda app nella pagina utente.

La scheda app elencherà:

  • Il nome dell’applicazione, ad esempio: (“Discourse Notifier”)
  • Ultimo utilizzo
  • Data di approvazione
  • Elenco degli ambiti di accesso concessi
  • Un pulsante revoca accesso in modo da poter revocare facilmente eventuali chiavi.

UI di autorizzazione della chiave API

Ogni chiave dovrà essere esplicitamente autorizzata dagli utenti finali in una pagina che spiega chiaramente cosa sta succedendo, ad esempio:

“Discourse Notifier” sta richiedendo il seguente accesso al tuo account:

  • Leggi e cancella notifiche
  • Leggi informazioni sulla sessione utente
  • Crea un token di accesso una tantum

[Autorizza]

Flusso di generazione della chiave API

L’API richiede un’unica richiesta GET dal lato utente.

https://sitename.com/user-api-key/new

:exclamation: A partire da Discourse 2.1, queste chiavi API utente ora scadono automaticamente se non utilizzate per lunghi periodi di tempo. L’impostazione del sito: revoke user api keys unused days è impostata su 180 di default.

Parametri:

  • auth_redirect: URL a cui reindirizzare con il token generato.
  • application_name: il nome dell’applicazione che effettua la richiesta (verrà visualizzato nella scheda App dell’account utente).
  • client_id: un identificatore univoco per il client.
  • nonce: un nonce univoco generato dal client. Questo verrà riportato nel payload crittografato in modo che il client possa verificare l’autenticità della risposta.
  • scopes: elenco separato da virgole degli ambiti di accesso consentiti per la chiave; vedere allow user api key scopes per l’elenco completo degli ambiti disponibili.
  • push_url: URL a cui inviare le notifiche push (richiesto e valido solo se push o notifications sono inclusi negli ambiti).
  • public_key: la parte pubblica della coppia di chiavi generata dal client.
  • padding (opzionale): la modalità di padding RSA da utilizzare per la crittografia del payload. I valori accettati sono pkcs1 (default) o oaep. OAEP è raccomandato per le nuove applicazioni.

Dopo che /user-api-key/new è stato chiamato con i parametri corretti, possono accadere 2 cose:

  1. Se l’utente non ha effettuato l’accesso, reindirizzeremo al login (dopo il login riprenderemo l’autorizzazione).
  2. Una volta che un utente ha effettuato l’accesso, gli verrà presentata l’UI di autorizzazione.

Dopo che l’autorizzazione è stata consentita, il sistema reindirizzerà all’URL definito in auth_redirect e includerà un parametro payload crittografato contenente un oggetto JSON con la chiave API utente generata (key), il nonce, lo stato push (push) e la versione API (api). Se è stato richiesto l’ambito one_time_password, verrà incluso anche un parametro di query oneTimePassword crittografato separato. client_id non viene riportato per maggiore sicurezza.

Controllo della versione API

L’API per l’utilizzo della chiave in Discourse è versionata. I client possono controllare la versione dell’API di un sito Discourse effettuando una richiesta HEAD a https://sitename.com/user-api-key/new. La risposta conterrà un’intestazione denominata Auth-Api-Version contenente il numero di versione dell’API del sito.

Utilizzo dell’API

L’utilizzo dell’API client sarà in qualche modo diverso dall’attuale API di amministrazione.

Il client può specificare 2 intestazioni:

User-Api-Key (richiesto): la chiave che è stata generata

e

User-Api-Client-Id (opzionale): fornire questo per aggiornare l’ID client memorizzato per questa api_key nel database.

Una volta specificate queste intestazioni, il client può eseguire richieste contro l’API proprio come farebbe normalmente.

Generazione di una password di accesso una tantum

A partire dalla versione 4, l’API include un ambito speciale: l’ambito one_time_password, che consente ai client di utilizzare la chiave API utente per generare una password una tantum. Se il client include questo ambito durante la generazione della chiave API seguendo i passaggi precedenti, una oneTimePassword crittografata verrà inclusa come parametro di query separato nel reindirizzamento al client.

In alternativa, il client può effettuare una richiesta GET a /user-api-key/otp con i seguenti parametri:

  • auth_redirect
  • application_name
  • public_key
  • padding (opzionale)

e con l’intestazione User-Api-Key.

Questa richiesta reindirizzerà a una schermata in Discourse che chiederà all’utente di consentire all’applicazione l’accesso al sito. Se l’utente approva, il sito reindirizzerà all’URL definito in auth_redirect e includerà un parametro oneTimePassword crittografato con una password una tantum che il client può utilizzare per accedere al sito richiedendo https://sitename.com/session/otp/ONE-TIME-PASSWORD. (La password una tantum è valida solo per 10 minuti.)

Revoca delle chiavi API

Per revocare una chiave API, effettuare una richiesta POST con l’intestazione User-Api-Key e nessun parametro a /user-api-key/revoke.


Ultima revisione da @SaraDev il 2022-07-13T00:00:00Z

30 Mi Piace
Generating User Api Keys with REST API
Discourse Login & Registeration
Discourse sso login using Rest API
Custom Push Notifications: allowed user api push urls
Beta testing the iOS mobile app
Secure way of encrypting payload in Javascript for user authentification
Can non-admin user issue their own API key?
How can I get user details via the user api key?
Authorization from a desktop application (and base domain site)
Is there any documentation on the User/Mobile API?
Get back Username with API Key?
Generating User Api Keys with REST API
Generating User Api Keys with REST API
API CORS Headers Incorrect
Automatic Login from iOS/Android app
Delegated authentication for Discourse Mobile app
Passing draft text into a new response
Discourse Hub "connect"
Generate User API Keys for testing
Consolidated API Requests in the thousands yet our site has no active API keys listed, is this a concern?
Having issue accessing the Discourse APIs from react app
Discourse REST API Documentation
Having issue accessing the Discourse APIs from react app
CORS error accessing API from javascript application
Does Discourse have support for PAT tokens?
API key creation
Access via Discourse API, key and/or user rejected
Feasibility of allowing a User Api Key client to register a valid auth_redirect
Implement discourse Apple login using API
Thousands of user api requests and invalidation
Are User API Keys Not Generated When Logging in via Login Link?
Confusion about API Authenticated User
Confusion about API Authenticated User
Generate User Api Key Without User Approval
How to use discourse api in react native?
"Api-Key" and "Api-Username" for try.discourse.org?
How can I allow users to like posts using RESTapi
Allow_user_api_key这个设置在哪开启
Dexo - A Native iOS Client for Discourse
'Clip To Discourse' Chrome Extension
'Clip To Discourse' Chrome Extension
Unable to create "Single User" level API key, always defaults to "All Users"
Discourse index
Authentication Protocol re: App Integration
Embed Discourse in a native app?
Request header field User-Api-Key is not allowed by Access-Control-Allow-Headers
Request header field User-Api-Key is not allowed by Access-Control-Allow-Headers
Request header field Content-Type is not allowed by Access-Control-Allow-Headers
Improve BAD CSRF error message when making API calls with content-type application/json
Create apikey for user programmatically as admin
How to fix 'Cannot read property '_links' of undefined'
Acess-Control-Allow-Headers CORS Error with API after updating discourse
Allow API use by regular users, not just admins
The purpose of the 2 Discourse API systems
Bot writer's tip: Processing every post
Using Zapier without being admin
Per User API Keys Not Working
Acess-Control-Allow-Headers CORS Error with API after updating discourse
Work with discourse users on an SPA

There are places I’ve strongly considered writing a delayed post tool, so I can compose a bunch of “word of the day” type things to keep going while I’m on vacation. Doing it without proper API access and pretending to be a browser seems somewhat more complicated than on other forum software.

(Just as an example of another use case.)

That is a good example, but keep in mind, our default will be only to enable read tokens, not write ones. Site admins will have to opt to allow write tokens.

Completely agree that the _t cookie hacks are a huge problem.

2 Mi Piace

Does max_user_api_calls_per_key_day setting apply to admin-created keys at /admin/api?

1 Mi Piace

Nope only to user api keys, we can look at adding extra limits for standard Api keys, it is a good safeguard

1 Mi Piace

To be clear, this is not implemented yet, correct?

No, it’s there (for almost 2,5 years now) - Admin - Settings - User API.

4 Mi Piace

As of Discourse 2.1 these user api keys now auto-expire if left unused for long periods of time, correct @sam?

2 Mi Piace

Correct the site setting: expire user api keys days is set to 180 out of the box.

2 Mi Piace

Okay, but you have to have admin access to see that page yes? And as an admin, it seems I can only create 1 key, so can’t create many keys for different users. confused.

1 Mi Piace

What are you trying to accomplish? It’s not clear because there is this (user api keys) and regular API tokens (which is what I think you are after) that admins can create for multiple users, but you have to do that from the individual user’s page inside of the admin dashboard by clicking on the “generate” button on the “API Key” field.

4 Mi Piace

Thanks! Yes, “regular API tokens” for users is what i was after. I’m sure I’d seen that a million times, and never realized it was there. :heavy_check_mark:

3 Mi Piace

Hey everyone I’m not sure if this was resolved? I see that it’s possible to create an “All Users” and (per user) level API token as an admin, but I’m interested in giving a user the power to generate his/her own token. Has there been work done on this? It sounds like the original thread was getting at this idea, and then it was lost. Thanks!

Download the mobile App and then add a site, that uses the user api key system you have to follow a very strict workflow, no plans to expose arbitrary generation of keys in user prefs

3 Mi Piace

Thank you! I downloaded the app, and then realized that the sites I belong to don’t have this enabled (I’ve been testing on my local machine with the Dockerized discourse). Just to make sure we are talking about the same thing - I’m interested in generating tokens to use just a scoped subset of functions (and not global API keys to do all the things). Is this what you are talking about?

It seems like, given that there is an endpoint to generate tokens, it would be logical to provide this function (to users with a certain trust level, for example) from within the site. Otherwise, it would need to be the case that the site generates some external page (with a server to hide an admin token) to generate the keys for the user. Is it the case that 1. there is no internal generation of tokens for the user (and why not?) and 2. Nobody has created some external app (javascript, flask, anything really) to perform this action?

1 Mi Piace

Yes.

Possibly, conceptually

  1. This is tricky to consume cause you need to use custom HTTP headers (by design)

  2. It would be very hard to educate even TL3 users about what the point is of this thing.

I prefer not to ship UI for this in core, but maybe you should write a plugin for your specific use case?

Can you explain a bit more about the “why” here?

The design of the system centers around “I have an external dedicated program”, “this program knows how to follow Discourse protocol”, “It asks for token”

API keys (non user ones) are much easier to consume cause you just append them after the ?

4 Mi Piace

Can I pass the API key generated from the user page on this? I was trying to use that API key and seeing ‘You are not permitted to view the requested resource.’ error on /categories.json API request

Ciao a tutti

Mi scuso se è una duplicazione, ma sto avendo difficoltà a comprendere i passaggi indicati, anche se sono molto ben organizzati.

Ho un’installazione di Discourse su https://forum.domain.com e un sito su https://development.domain.com da cui devo effettuare chiamate all’installazione di Discourse per recuperare e impostare alcuni dati.

Tutte le richieste funzionano da Postman con Api-Username e Api-Key senza problemi.

Tuttavia, per le richieste cross-origin tramite JavaScript, Discourse non consente l’uso di Api-Username, portandomi a seguire il flusso descritto in questo thread, ovvero l’uso di User-Api-Key e User-Api-Client-Id.

Ho bisogno principalmente di una descrizione dei parametri PUBLIC_KEY, NONCE e CLIENTID utilizzati nella richiesta di esempio qui sotto e di sapere dove ottenerli…

https://forum.domain.com/user-api-key/new?public_key=PUBLIC_KEY&nonce=NONCE&scopes=SCOPES&client_id=CLIENTID&application_name=DEVELOP&auth_redirect=XXX

Infine, questo flusso consentirà richieste API fluide dal mio https://development.domain.com a https://forum.domain.com senza necessità di autenticazione?

PS: Ho configurato l’SSO tra il forum e il sito da cui vengono effettuate le richieste, quindi l’utente sarà già loggato.

Grazie per qualsiasi indicazione

Un attimo, è una cosa per utente? State permettendo a utenti arbitrari di fare questo?

La nostra API server supporta l’autenticazione basata su header al giorno d’oggi, quindi può funzionare con CORS proprio come fanno le chiavi API utente. Utilizzeresti le chiavi API utente se vuoi limitare gli ambiti e permettere agli utenti finali di generare le chiavi invece che agli amministratori.

2 Mi Piace

Non penso che ogni utente debba avere una chiave separata… Dovrebbe bastare una sola chiave amministrativa per le mie esigenze.

Posso utilizzare l’API senza problemi tramite Postman. Ad esempio, una richiesta GET a /notifications.json?username=alanmurphy restituisce i dati correttamente usando solo api-key come header.

Se provo a eseguire quella richiesta dalla console di un’installazione Discourse, ottengo comunque i dati senza problemi, ovvero:

var xhr = new XMLHttpRequest();
xhr.addEventListener(“readystatechange”, function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open(“GET”, “https://**********.com/notifications.json?username=alanmurphy”);
xhr.setRequestHeader(“api-key”, “d06ca53322d1fbaf383a6394d6c229e56871342d2cad953a0fe26c19df7645ba”);
xhr.setRequestHeader(“api-userame”, “system”);
xhr.send();

Tutto a posto:+1:

Tuttavia, se provo a farlo dal sottodominio da cui desidero contattare Discourse, mi viene segnalato che la richiesta è bloccata dalla policy CORS: il campo dell’header api-key non è consentito da Access-Control-Allow-Headers.

Gli header consentiti sono:

Content-Type, Cache-Control, X-Requested-With, X-CSRF-Token, Discourse-Visible, User-Api-Key, User-Api-Client-Id

Se potessi ricevere indicazioni su quali parametri di autenticazione passare per le richieste cross-origin e dove ottenerli, sarebbe molto utile.

Ps. Il mio Discourse è configurato per consentire richieste cross-origin dal dominio, quindi credo che il problema riguardi esclusivamente gli header.

Grazie

1 Mi Piace