Base OAUTH2 - un incubo :-(

Ciao ragazzi,

Sto provando a configurare OAUTH2 da 2 giorni e ho problemi.

Ho configurato tutto secondo la documentazione, ma continuo a ricevere questo:

(oauth2_basic) Authentication failure! invalid_scope: OmniAuth::Strategies::OAuth2::CallbackError, invalid_scope | Unknown/invalid scope(s)
Started GET "/auth/failure?message=invalid_scope&origin=<censored>%2Latest&strategy=oauth2_basic" for 10.153.107.106 at 2024-11-27 05:30:33 +0000
Processing by Users::OmniauthCallbacksController#failure as HTML
  Parameters: {"message"=>"invalid_scope", "origin"=>"<censored>/latest", "strategy"=>"oauth2_basic"}

La mia configurazione sulla bacheca (per quanto riguarda gli scope) è la seguente:

L’IdP è configurato in questo modo:

Qualcuno ha un suggerimento su come fare un debug più approfondito:

Curl utili, con cui potrei testare, o un output di debug migliore (ho già attivato l’opzione di debug avanzato)?

Sto impazzendo per questo :frowning:

Grazie e saluti!

WS

AGGIORNAMENTO:

Ho appena reimpostato le opzioni su solo “scope”

ma non ha funzionato :frowning:

2 Mi Piace

notato che il nostro IdP aveva lo scope sbagliato sulla sua interfaccia utente…

openId è sull’interfaccia utente
openid è quello reale :slight_smile:
un passo avanti, ma ora sto ricevendo un timeout
image
dopo questa chiamata


OAuth2 Debugging: request POST https://<myAuthProvider/auth/oauth2/realms/root/realms/<realm>/access_token

Headers:
--- !ruby/hash-with-ivars:Faraday::Utils::Headers
ivars:
  :@names:
    user-agent: User-Agent
    content-type: Content-Type
elements:
  User-Agent: Faraday v2.12.1
  Content-Type: application/x-www-form-urlencoded


Body:
---
client_id: <client-id>
client_secret: <client-secret>
grant_type: authorization_code
code: <code
redirect_uri: https://<myDiscourse>/auth/oauth2_basic/callback

che termina con


Ma dato che la chiamata di autorizzazione che ottiene il codice è andata a buon fine, non ci possono essere problemi di rete, giusto?

1 Mi Piace

Quando emito la chiamata con un curl

curl --request POST \
  --url https://<IdP address>/auth/oauth2/realms/root/realms/<realm>/access_token \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data client_id=<clientId> \
  --data client_secret=<secret> \
  --data grant_type=authorization_code \
  --data code=<code > \
  --data redirect_uri=https://<discourse>/auth/oauth2_basic/callback

dal contenitore docker di discourse ottengo questo

{
  "access_token": "<token>",
  "refresh_token": "<refresh_token>",
  "scope": "openid profile email",
  "id_token": "<censored>",
  "token_type": "Bearer",
  "expires_in": 7199
}

Potrebbe essere un problema a causa di questo?

image

Questi campi non sono nella risposta :frowning:

2 Mi Piace

Nessuno? :disappointed_face:

1 Mi Piace

Sono molto interessato all’argomento perché sto ricercando la quantità di sforzo che sarebbe necessaria per la mia prima pagina di discussione per il mio quartiere e poi gradualmente per le scuole dei miei figli. Sono sovraccarico di notifiche da tutte le diverse piattaforme.
Ridurre l’attrito verso la pagina è fondamentale, quindi vorrei offrire un aiuto. Sono un principiante in ruby, quindi posso offrire solo alcune risorse che ho trovato e idee su tali risorse.

Potresti averci già dato un’occhiata, ma potresti voler controllare il repository su github per discourse-openid-connect

Il repository ha 37 collaboratori e immagino che uno di loro sarebbe in grado di aiutarti a rispondere alla tua domanda.

Spero che questo aiuti perché questa è un’ottima domanda.

1 Mi Piace

Ciao @thecatfix,

sembra promettente. Lo proverò subito e ti darò un feedback al più presto.
Purtroppo oggi non ho tempo. Forse potrò lavorarci nel fine settimana.

Grazie mille e buon fine settimana!

Ciao,

non ho potuto aspettare e l’ho testato oggi, ma in qualche modo i ragazzi del nostro reparto EAM hanno pasticciato questa scoperta. Non funziona e ricevo un client non valido - autenticazione fallita nonostante sia sicuro al 1000% che le credenziali funzionino (testato con curl)
Quindi sono tornato all’inizio.

La cosa interessante è che ricevo sempre un timeoutError per la richiesta all’endpoint di autorizzazione, e arriva abbastanza velocemente.


Faraday::TimeoutError (Net::ReadTimeout with #<TCPSocket:(closed)>)

Ho trovato questo e sono curioso se qualcosa del genere sia possibile anche in discourse?

Non sono affatto un esperto di Ruby, quindi avrò bisogno di aiuto.

Voglio eseguire il debug di ogni singola richiesta gestita dal lato discourse. È possibile?
Ho anche pensato di installare un proxy locale per intercettare le chiamate, ma prima di addentrarmi in questo volevo chiedere se ci sono metodi più semplici :slight_smile:

Vuoi visualizzare il traffico HTTP grezzo o essere in grado di entrare nel codice?

Il traffico grezzo…

richieste inviate con header e payload…

è possibile in qualche modo?

Il modo più semplice per farlo è dall’interno del container; puoi intercettare e stampare le richieste tra nginx e Discourse entrando nel container ed eseguendo:

apt-get update && apt-get -y install scapy
scapy

# al prompt di scapy, incolla:
class Callback:
  def __init__(self):
    self.last = None
  def prn(self, p):
    if p != self.last: # i pcap su lo catturano due volte
      self.last = p
      p.hide_defaults()
      print(repr(p)) # questa riga stampa il pacchetto, tienila o lasciala
      if scapy.packet.Raw in p.layers():
        try:
          print(p.load.decode())
        except:
          print(p.load)

sniff(filter="port 3000", iface="lo", prn=Callback().prn)
1 Mi Piace

Questo è enorme, grazie… stavo cercando esattamente uno strumento del genere!

Hmmm… ma
sembra che discourse riceva il callback e poi…
Secondo la mia comprensione, dovrebbe quindi contattare l’endpoint userinfo e ottenere le informazioni utente con il codice recuperato, ma sto ottenendo un HTTP 500


GET /auth/oauth2_basic/callback?code=_B1HRB1e6kZKc8nuGLkzGC8&iss=https%3A%2F%2F%3CmyAuthDomain%3E%3A443%2Fauth%2Foauth2%2Frealms%2Froot%2Frealms%2Fintranetrealm&state=544801ae7e8262ea1667ea7531487f28e83aae232d5182b4&client_id=eadaa55a-1697-494a-8fg5-bb1137c68caa HTTP/1.0
Host: <discourseHost>
X-Request-Start: t=1732956951.485
X-Real-IP: 10.111.101.84
X-Forwarded-For: 10.131.101.84
X-Forwarded-Proto: https
Connection: close
cache-control: max-age=0
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
sec-fetch-site: same-site
sec-fetch-mode: navigate
sec-fetch-user: ?1
sec-fetch-dest: document
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
referer: https://discourseHost/
accept-encoding: gzip, deflate, br, zstd
accept-language: de-DE,de;q=0.9
priority: u=0, i
cookie: lbwdn=01; win=teUNUPSc8oibB......

<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=52 id=7742 flags=DF frag=0 ttl=127 proto=tcp chksum=0xdf83 src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33574 seq=271589520 ack=3955524768 dataofs=8 flags=A window=499 chksum=0xfe28 options=[('NOP', None), ('NOP', None), ('Timestamp', (3962821542, 3962821542))] |>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=281 id=55898 flags=DF frag=0 ttl=127 proto=tcp chksum=0x2282 src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33530 seq=491394 ack=1852886175 dataofs=8 flags=PA window=507 chksum=0xff0d options=[('NOP', None), ('NOP', None), ('Timestamp', (3962823893, 3962816870))] |<Raw  load='HTTP/1.1 500 Internal Server Error\r\nDate: Sat, 30 Nov 2024 08:55:53 GMT\r\nConnection: close\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: 658\r\nX-Request-Id: 7f4bafa0-7590-4b9b-8b8d-70a4fa1ae6c5\r\nX-Runtime: 10.078459\r\n\r\n' |>>>
HTTP/1.1 500 Internal Server Error
Date: Sat, 30 Nov 2024 08:55:53 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 658
X-Request-Id: 7f4bafa0-7590-4b9b-8b8d-70a4fa1ae6c5
X-Runtime: 10.078459

.....

<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=52 id=15439 flags=DF frag=0 ttl=127 proto=tcp chksum=0xc172 src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=33574 dport=3000 seq=3955524768 ack=271589749 dataofs=8 flags=A window=511 chksum=0xfe28 options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |>
<Ether  dst=00:00:00:00:00:00 src=00:00:00:00:00:00 type=IPv4 |<IP  ihl=5 len=710 id=7744 flags=DF frag=0 ttl=127 proto=tcp chksum=0xdcef src=127.0.0.1 dst=127.0.0.1 |<TCP  sport=3000 dport=33574 seq=271589749 ack=3955524768 dataofs=8 flags=PA window=512 chksum=0xbb options=[('NOP', None), ('NOP', None), ('Timestamp', (3962831618, 3962831618))] |<Raw  load='<!DOCTYPE html>\n<html>\n<head>\n  <title>Oops - Error 500</title>\n  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">\n</head>\n<body>\n    <h1>Oops</h1>\n    <p>The software powering this discussion forum encountered an unexpected problem. We apologize for the inconvenience.</p>\n    <p>Detailed information about the error was logged, and an automatic notification generated. We\'ll take a look at it.</p>\n    <p>No further action is necessary. However, if the error condition persists, you can provide additional detail, including steps to reproduce the error, by posting a discussion topic in the site\'s feedback category.</p>\n</body>\n</html>\n' |>>>>
<!DOCTYPE html>
<html>
<head>
  <title>Oops - Error 500</title>
.....

Nei log vengono stampate queste righe

Uno screenshot che mostra un errore di rete con timeout, inclusi gli header HTTP e i dettagli dell'errore. (Sottotitolato dall'IA)

A me sembra che Discourse abbia problemi a gestire il callback e ora avrei bisogno di una visione più approfondita di ciò che accade dietro le quinte in Discourse.

Non ottengo alcun suggerimento nei log, nonostante abbia attivato ogni modalità di debug che conosco.

Hmmm, sono davvero bloccato con questo ed è frustrante :frowning:

Ciao ragazzi,

Sono molto più avanti adesso :slight_smile:

Aveva a che fare con la nostra infrastruttura EAM…

Ora ho il prossimo problema, però :smiley:

Il mio userinfotoken è così:


{
  "company-i": "A1",
  "accounting-code": "5806",
  "given_name": "Mister",
  "family_name": "Bean",
  "name": "Mister Bean",
  "departmentnumber": "Covert Operations",
  "salutation": "Dude",
  "description": "Some description",
  "preferredlanguage": "DE",
  "inumber": "723jfio-7zwe8489",
  "employeenumber": "36484332",
  "employeetype": "BigCompany",
  "uid": "f57383",
  "adupn": "f57383@europe.bigcom.corp",
  "uniqueuid": "f57383",
  "uniqueuidq": "f57383",
  "loginname": "f57383",
  "email": "Mister.Bean@bigcom.corp",
  "sub": "f57383",
  "subname": "f57383"
}

E sto ricevendo questo errore nei log:


ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR:  null value in column "provider_uid" of relation "user_associated_accounts" violates not-null constraint
DETAIL:  Failing row contains (6, oauth2_basic, null, null, 2024-12-03 13:06:49.831182, {"name": "Mister Bean", "email": "Mister.Bean@bigcom.corp", "user..., {"token": "dszghsdhsdfoph", "expires": true, "expir..., {}, 2024-12-03 13:06:49.831362, 2024-12-03 13:06:49.831362).

Discourse non sembra essere in grado di mappare la risposta da userinfoendpoint ai suoi nomi interni.

Ho provato a configurarlo tramite l’interfaccia utente:

ma probabilmente in modo errato.

Qualcuno potrebbe darmi un suggerimento su come configurarlo?

Grazie e saluti,

WS

Il campo oauth2 json user id path è compilato?

Assicurati che questi valori siano impostati: https://meta.discourse.org/t/configure-sign-up-and-log-in-with-auth0-using-the-oauth2-basic-plugin/64633#configure-discourse-3.

Ciao,\n\ngrazie per la risposta.\n\nSembra che il mio provider non invii i campi provider_name e provider_uid, e quindi discourse tenta di creare la voce senza di essi e ottiene una violazione NotNull.\nMa non è responsabilità del plugin (oauth2_basic) compilare questi valori (se nessuno proviene dall’IdP remoto)?\nMi aspetterei qualcosa del tipo\n\nprovider_name: "oauth2_basic"\nprovider_uid: "1234"\n\nUtilizzato automaticamente ad ogni login utente… :frowning:

Il provider_name è impostato su oauth2_basic e il provider_uid sarà quello che inserirai in oauth2 json user id path.

Devi solo impostare questa impostazione del sito sul percorso dell’ID in base a ciò che restituisce il tuo provider. Il plugin utilizza questo percorso JSON per compilare il provider_uid, quindi se è attualmente vuoto o un percorso che non esiste, il valore sarà nil.

Dal tuo JSON sopra sembra che il valore debba essere sub.

2 Mi Piace

Ma l’ho fatto…

Hai ragione, il percorso dovrebbe essere “sub”, ma l’ho configurato qui

Aspetta… Avevi ragione, e io sono stupido :frowning:

Impostazione sbagliata…

Ora funziona!

2 Mi Piace

C’è un modo per salvare queste impostazioni da qualche parte :smiley:
fare un backup solo delle impostazioni di configurazione?

Sono nel database?

È fantastico.

Tutte le impostazioni del sito sono salvate nel database. Supponendo che tu abbia accesso alla console di Rails, quanto segue dovrebbe mostrarti un elenco delle impostazioni.

SiteSetting.where("name LIKE 'oauth2_%'").pluck(:name, :value)

Puoi anche semplicemente creare un backup.