SSO personalizzato non funziona dopo l'aggiunta di secure_session come parametro

Ciao! Abbiamo sviluppato un plugin SSO personalizzato per raggruppare le credenziali di accesso della nostra azienda in un pacchetto utilizzabile da Discourse per gestire gli accessi e la creazione degli account. Con la versione v2.7.0beta4, abbiamo iniziato a ricevere errori relativi alla mancata fornitura di un nuovo parametro: secure_session. Non riesco a trovare alcuna informazione sul formato che questo parametro dovrebbe avere o sul suo contenuto. Esiste una documentazione aggiuntiva per questo aggiornamento?

Grazie!

1 Mi Piace

Sai qual è il messaggio di errore esatto che stai visualizzando? La mia comprensione è che Discourse ora lega il parametro nonce dell’SSO alla sessione dell’utente. Ciò significa che se un’app sta generando il nonce effettuando una richiesta in background a /session/sso, il nonce non sarà valido. È possibile che questo sia il problema che stai riscontrando.

2 Mi Piace

Certamente! Ecco lo stack di errore che stiamo osservando nel nostro APM:

ArgumentError: missing keyword: :secure_session
…r/www/discourse/app/models/discourse_single_sign_on.rb:   28:in `initialize'
               /var/www/discourse/lib/single_sign_on.rb:   65:in `new'
               /var/www/discourse/lib/single_sign_on.rb:   65:in `parse'
…ourse_account_auth/lib/service_gateway_current_user.rb:   72:in `upsert_sso_record'
…ourse_account_auth/lib/service_gateway_current_user.rb:   53:in `create_sso_record'
…ourse_account_auth/lib/service_gateway_current_user.rb:   28:in `current_user'
                 /var/www/discourse/lib/current_user.rb:   36:in `current_user'

Il file service_gateway_current_user.rb fa parte del nostro plugin per costruire il payload da inviare a DiscourseSingleSignOn in base alle intestazioni “Service Gateway” (“Service Gateway” è la nostra struttura interna aziendale per determinare se l’utente è loggato nel nostro sistema).

Per spiegare quella parte dello stack:

  • La nostra funzione current_user utilizza le intestazioni per cercare un SingleSignOnRecord in cui external_id corrisponde all’ID utente nelle intestazioni. Se non è così, passiamo alla sezione create_sso_record.
  • create_sso_record crea un hash – { external_id: sg_headers[:user_id], email: sg_headers[:email] } – e lo invia alla nostra funzione upsert_sso_record.
  • upsert_sso_record prende quell’hash (payload nel contesto sottostante) e tenta di creare un oggetto DiscourseSingleSignOn:
def upsert_sso_record(payload)
  encoded_query = Base64.encode64(payload.to_query)
  sig = OpenSSL::HMAC.hexdigest('sha256', ENV['SSO_SECRET'], encoded_query)
  sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query)

  if SiteSetting.verbose_sso_logging
    Rails.logger.warn("Verbose SSO log: Started SSO process\n\n#{sso.diagnostics}")
    Rails.logger.warn("SSO Payload:\n\n#{payload}")
  end

  begin
    user = sso.lookup_or_create_user(@request.ip)
  rescue ActiveRecord::RecordInvalid => ex
    Rails.logger.error "Unable to find/create sso user #{ex}"
  end
  user
end

La chiamata a parse sulla terza riga di quella funzione è dove sembra manifestarsi il problema. Non appena tenta di initialize l’oggetto, il valore secure_session che si aspetta non è presente.

2 Mi Piace

Aggiornamento! Anch’io sono curioso/a di sapere questo!

Mi chiedo se impostare la nuova impostazione del sito discourse_connect_csrf_protection su false possa risolvere il problema per te. Questa impostazione del sito è nascosta, quindi deve essere configurata dalla console di Rails. Puoi trovare dettagli al riguardo nelle risposte a questo argomento: DiscourseConnect flow no longer functions.

Purtroppo, non credo che questa nuova impostazione sia sufficiente da sola: gli interni del codice richiederanno comunque il passaggio di un oggetto secure_session, anche se non viene utilizzato.

In generale, consigliamo di utilizzare gli hook ufficiali per i plugin di autenticazione, invece di sovrascrivere l’implementazione di DiscourseConnect del core.

È difficile essere certi senza vedere l’intero plugin, ma potresti provare a passare un valore nil per secure_session. Fare questo, insieme all’attivazione della nuova impostazione del sito, potrebbe aiutare a far funzionare le cose un po’ meglio.

5 Mi Piace

Dopo aver analizzato ulteriormente il codice di v2.7.0.beta4, vedo che ApplicationController ha una definizione secure_session. Modificare il nostro codice del plugin come segue sembra funzionare nel nostro ambiente di Staging:

sso = DiscourseSingleSignOn.parse({ sso: encoded_query, sig: sig }.to_query, secure_session: secure_session)

…È davvero così semplice? :thinking:

Sembra che dovrebbe funzionare: la sessione sicura proviene normalmente da quel metodo nell’ApplicationController. :slight_smile:

2 Mi Piace

Fantastico! Grazie per avermi aiutato a chiarire questo problema. :duck: :metal:

2 Mi Piace