SSO LinkedIn Personalizzato: differenze tra le versioni
Nessun oggetto della modifica |
Nessun oggetto della modifica |
||
(Una versione intermedia di uno stesso utente non è mostrata) | |||
Riga 194: | Riga 194: | ||
<code>/oauth/linkedin-login.php</code> | <code>/oauth/linkedin-login.php</code> | ||
3. Verifica nei log se la creazione dell’utente avviene correttamente. | 3. Verifica nei log se la creazione dell’utente avviene correttamente. | ||
4. Controlla la pagina <code>Special:Users</code> per vedere se l’utente è stato registrato. | 4. Controlla la pagina <code>Special:Users</code> per vedere se l’utente è stato registrato. | ||
Riga 206: | Riga 207: | ||
---- | ---- | ||
== Documentazione tecnica completa - SSO LinkedIn su MediaWiki (Masticationpedia) == | |||
🧠 Obiettivo del sistema SSO LinkedIn | |||
Consentire agli utenti di Masticationpedia di accedere direttamente al sito tramite il proprio profilo LinkedIn, senza registrazione manuale. L’utente viene autenticato tramite OAuth2 (OpenID Connect) e, se non esiste già, viene creato automaticamente nel database MediaWiki e visibile su `Special:Users`. | Consentire agli utenti di Masticationpedia di accedere direttamente al sito tramite il proprio profilo LinkedIn, senza registrazione manuale. L’utente viene autenticato tramite OAuth2 (OpenID Connect) e, se non esiste già, viene creato automaticamente nel database MediaWiki e visibile su `Special:Users`. | ||
✅ Risultati ottenuti | |||
Al momento attuale (luglio 2025), il sistema ha raggiunto diversi traguardi fondamentali: | Al momento attuale (luglio 2025), il sistema ha raggiunto diversi traguardi fondamentali: | ||
Riga 220: | Riga 223: | ||
* I log di debug sono ben strutturati (incoming\_user\_debug.json, mw\_user\_creation.log) | * I log di debug sono ben strutturati (incoming\_user\_debug.json, mw\_user\_creation.log) | ||
❌ Problema attuale (blocco finale) | |||
Nonostante il flusso OAuth appaia corretto: | Nonostante il flusso OAuth appaia corretto: | ||
1. **L’utente non compare in `Special:Users`**, né risulta registrato in modo persistente da MediaWiki. | 1. **L’utente non compare in `Special:Users`**, né risulta registrato in modo persistente da MediaWiki. | ||
2. I file di debug non vengono più scritti (es: `incoming_user_debug.json` è vuoto), anche se fino a poco prima funzionavano. | 2. I file di debug non vengono più scritti (es: `incoming_user_debug.json` è vuoto), anche se fino a poco prima funzionavano. | ||
3. In alcuni tentativi recenti, **LinkedIn ha bloccato il flusso** reindirizzando su una pagina interna di errore: `challenge_global_internal_error`. | 3. In alcuni tentativi recenti, **LinkedIn ha bloccato il flusso** reindirizzando su una pagina interna di errore: `challenge_global_internal_error`. | ||
🧪 Possibili cause analizzate | |||
🔹 1. LinkedIn blocca il flusso con errore interno === | |||
* Dopo numerosi tentativi ravvicinati, LinkedIn ha mostrato CAPTCHA e poi un errore generico con redirect su `/checkpoint/lg/login?errorKey=challenge_global_internal_error`. | * Dopo numerosi tentativi ravvicinati, LinkedIn ha mostrato CAPTCHA e poi un errore generico con redirect su `/checkpoint/lg/login?errorKey=challenge_global_internal_error`. | ||
Riga 236: | Riga 241: | ||
* Tuttavia, il login classico sul sito LinkedIn funziona, quindi l'account **non è bannato**. | * Tuttavia, il login classico sul sito LinkedIn funziona, quindi l'account **non è bannato**. | ||
🔹 2. Il file `create_mw_user_direct.php` non viene nemmeno raggiunto === | |||
* Potrebbe essere dovuto a un errore nella `curl_exec` finale nel callback. | * Potrebbe essere dovuto a un errore nella `curl_exec` finale nel callback. | ||
Riga 242: | Riga 247: | ||
* Nessuna scrittura su `incoming_user_debug.json` è un forte indizio che l'esecuzione si ferma prima. | * Nessuna scrittura su `incoming_user_debug.json` è un forte indizio che l'esecuzione si ferma prima. | ||
🔹 3. La fase di scrittura su MediaWiki fallisce silenziosamente | |||
* Anche quando tutto sembra completarsi, l’utente non è visibile. | * Anche quando tutto sembra completarsi, l’utente non è visibile. | ||
* MediaWiki potrebbe accettare la richiesta ma non completare il commit nel database. | * MediaWiki potrebbe accettare la richiesta ma non completare il commit nel database. | ||
🧰 Diagnostica svolta | |||
* Test del singolo script `create_mw_user_direct.php` → funzionante in locale. | * Test del singolo script `create_mw_user_direct.php` → funzionante in locale. | ||
Riga 254: | Riga 259: | ||
* Permessi `755` per i file PHP confermati. | * Permessi `755` per i file PHP confermati. | ||
📌 Prossimi tentativi suggeriti == | |||
1. **Verificare i permessi su tutta la cartella `/oauth/`**, specialmente se `www-data` ha accesso in scrittura. | 1. **Verificare i permessi su tutta la cartella `/oauth/`**, specialmente se `www-data` ha accesso in scrittura. | ||
2. **Inserire `var_dump()` o `echo` diagnostici in cima ai file** per vedere se si attivano realmente. | 2. **Inserire `var_dump()` o `echo` diagnostici in cima ai file** per vedere se si attivano realmente. | ||
3. **Ripristinare uno script minimo** che scriva sempre qualcosa, anche senza passaggi LinkedIn, per confermare che la `curl` arrivi. | 3. **Ripristinare uno script minimo** che scriva sempre qualcosa, anche senza passaggi LinkedIn, per confermare che la `curl` arrivi. | ||
4. **Pulire cache LinkedIn** o aspettare 24-48h dopo l’errore `challenge_global_internal_error`. | 4. **Pulire cache LinkedIn** o aspettare 24-48h dopo l’errore `challenge_global_internal_error`. | ||
5. **Verificare la variabile `client_id` e `client_secret`**: in uno degli ultimi tentativi era errata e ha mandato in confusione il flusso. | 5. **Verificare la variabile `client_id` e `client_secret`**: in uno degli ultimi tentativi era errata e ha mandato in confusione il flusso. | ||
🧩 Conclusione provvisoria | |||
Il sistema è quasi completo. La parte più difficile (flusso OAuth, access token, lettura dati utente) è superata con successo. | Il sistema è quasi completo. La parte più difficile (flusso OAuth, access token, lettura dati utente) è superata con successo. | ||
Riga 271: | Riga 281: | ||
* Il logging per capire il vero punto di blocco. | * Il logging per capire il vero punto di blocco. | ||
🔐 Nota finale | |||
Si raccomanda di: | Si raccomanda di: | ||
Riga 281: | Riga 292: | ||
''Pagina privata generata da ChatGPT su richiesta del fondatore di Masticationpedia, Gianni Frisardi.'' | ''Pagina privata generata da ChatGPT su richiesta del fondatore di Masticationpedia, Gianni Frisardi.'' | ||
== Appendice == | |||
<syntaxhighlight lang="php"> | |||
<?php | |||
// linkedin-login.php | |||
$client_id = 'TUO_CLIENT_ID'; | |||
$redirect_uri = 'https://staging.masticationpedia.org/oauth/linkedin-callback.php'; | |||
$scope = 'openid email profile'; | |||
$state = bin2hex(random_bytes(16)); | |||
$url = "https://www.linkedin.com/oauth/v2/authorization?response_type=code" | |||
. "&client_id={$client_id}" | |||
. "&redirect_uri=" . urlencode($redirect_uri) | |||
. "&state={$state}" | |||
. "&scope=" . urlencode($scope); | |||
header("Location: $url"); | |||
exit; | |||
</syntaxhighlight> |
Versione attuale delle 09:06, 5 lug 2025
Documentazione Tecnica SSO LinkedIn per Masticationpedia
Questa pagina descrive la struttura tecnica per integrare il login Single Sign-On (SSO) tramite LinkedIn, con creazione automatica dell’utente su MediaWiki.
Tutti i file sono caricati nella cartella: /oauth/
📁 1. linkedin-login.php
<?php
// linkedin-login.php
$client_id = 'TUO_CLIENT_ID';
$redirect_uri = 'https://staging.masticationpedia.org/oauth/linkedin-callback.php';
$scope = 'openid email profile';
$state = bin2hex(random_bytes(16));
$url = "https://www.linkedin.com/oauth/v2/authorization?response_type=code"
. "&client_id={$client_id}"
. "&redirect_uri=" . urlencode($redirect_uri)
. "&state={$state}"
. "&scope=" . urlencode($scope);
header("Location: $url");
exit;
Funzione: Genera l'URL di richiesta login e consensi a LinkedIn. Avvia il flusso OAuth2.
📁 2. linkedin-callback.php
<?php
// linkedin-callback.php
ini_set('display_errors', 1);
error_reporting(E_ALL);
$log = __DIR__ . '/linkedin_callback.log';
function log_debug($msg) {
global $log;
file_put_contents($log, "[".date('Y-m-d H:i:s')."] $msg\n", FILE_APPEND);
}
if (!isset($_GET['code'], $_GET['state'])) exit('Errore: code/state mancanti');
$code = $_GET['code'];
$token_url = 'https://www.linkedin.com/oauth/v2/accessToken';
$post = [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => 'https://staging.masticationpedia.org/oauth/linkedin-callback.php',
'client_id' => 'TUO_CLIENT_ID',
'client_secret' => 'TUO_CLIENT_SECRET'
];
$ch = curl_init($token_url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($post),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false
]);
$resp = curl_exec($ch);
curl_close($ch);
$data = json_decode($resp, true);
$token = $data['access_token'] ?? '';
if (!$token) exit('Errore token');
$ch2 = curl_init('https://api.linkedin.com/v2/userinfo');
curl_setopt_array($ch2, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ["Authorization: Bearer $token"],
CURLOPT_SSL_VERIFYPEER => false
]);
$userinfo = curl_exec($ch2);
curl_close($ch2);
$user = json_decode($userinfo, true);
$sub = $user['sub'] ?? '';
$name = $user['name'] ?? '';
$email = $user['email'] ?? '';
if (!$sub || !$name) exit('Errore dati incompleti');
$ch3 = curl_init('https://staging.masticationpedia.org/oauth/create_mw_user_direct.php');
curl_setopt_array($ch3, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'sub' => $sub,
'name' => $name,
'email' => $email
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false
]);
curl_exec($ch3);
curl_close($ch3);
header("Location: https://staging.masticationpedia.org/wiki/Main_Page");
exit;
?>
Funzione: Scambia il code con un token, ottiene i dati da LinkedIn e li invia al file che crea l'utente.
📁 3. create_mw_user_direct.php
<?php
use MediaWiki\MediaWikiServices;
ini_set('display_errors', 1);
error_reporting(E_ALL);
$log = __DIR__ . '/mw_user_creation.log';
function log_debug($m) {
global $log;
file_put_contents($log, "[".date('Y-m-d H:i:s')."] $m\n", FILE_APPEND);
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
exit('❌ Metodo non consentito.');
}
$sub = $_POST['sub'] ?? 'no-sub';
$name = $_POST['name'] ?? 'Anon';
$email = $_POST['email'] ?? 'noemail@mpedia';
file_put_contents(__DIR__.'/incoming_user_debug.json',
json_encode(['ts'=>date('c'),'sub'=>$sub,'name'=>$name,'email'=>$email], JSON_PRETTY_PRINT)."\n", FILE_APPEND);
if (!$sub || !$name) {
log_debug("Missing user data");
http_response_code(400);
exit;
}
require_once __DIR__ . '/../includes/WebStart.php';
$services = MediaWikiServices::getInstance();
$userFactory = $services->getUserFactory();
$userLookup = $services->getUserLookup();
$username = substr(preg_replace('/[^A-Za-z0-9]/','_',$name . '_' . substr($sub,0,6)), 0, 50);
$userObj = \User::newFromName($username);
if ($userObj && $userObj->getId() !== 0) {
log_debug("User exists: $username");
exit;
}
$userObj = $userFactory->newFromName($username);
$userObj->addToDatabase();
$userObj->setEmail($email);
$userObj->setRealName($name);
$userObj->setToken();
$userObj->saveSettings();
$services->getDBLoadBalancerFactory()->commitMasterChanges(__METHOD__);
$entry = new \ManualLogEntry('newusers','create');
$entry->setPerformer($userObj);
$entry->setTarget($userObj->getUserPage());
$entry->setComment('Created via LinkedIn SSO');
$id = $entry->insert();
$entry->publish($id);
log_debug("User created: $username");
?>
Funzione: Riceve i dati utente da LinkedIn e crea direttamente un account MediaWiki completo, visibile in Special:Users.
✅ Riassunto finale
- **3 file**: `linkedin-login.php`, `linkedin-callback.php`, `create_mw_user_direct.php`
- **Cartella consigliata**: `/oauth/`
- **Log consigliati**:
* `linkedin_callback.log` * `incoming_user_debug.json` * `mw_user_creation.log`
🧪 Debug e test
1. Inserisci correttamente i tuoi `client_id` e `client_secret` nei file. 2. Collega il pulsante o link di login LinkedIn alla pagina:
/oauth/linkedin-login.php
3. Verifica nei log se la creazione dell’utente avviene correttamente.
4. Controlla la pagina Special:Users
per vedere se l’utente è stato registrato.
🔐 Sicurezza finale
Dopo la messa in produzione:
- Rimuovere le righe `ini_set('display_errors', 1)` e `log_debug(...)`
- Proteggere l'accesso alla cartella `/oauth/` se non strettamente necessario.
- Salvare backup regolari di `incoming_user_debug.json` e log.
Documentazione tecnica completa - SSO LinkedIn su MediaWiki (Masticationpedia)
🧠 Obiettivo del sistema SSO LinkedIn
Consentire agli utenti di Masticationpedia di accedere direttamente al sito tramite il proprio profilo LinkedIn, senza registrazione manuale. L’utente viene autenticato tramite OAuth2 (OpenID Connect) e, se non esiste già, viene creato automaticamente nel database MediaWiki e visibile su `Special:Users`.
✅ Risultati ottenuti
Al momento attuale (luglio 2025), il sistema ha raggiunto diversi traguardi fondamentali:
- Il pulsante di login LinkedIn apre correttamente la finestra di autorizzazione.
- LinkedIn restituisce il `code` e lo scambio con `access_token` funziona perfettamente.
- I dati dell’utente (sub, nome, email) vengono ricevuti correttamente.
- L’utente teoricamente viene creato tramite `create_mw_user_direct.php`, con salvataggio previsto su `Special:Users`.
- I log di debug sono ben strutturati (incoming\_user\_debug.json, mw\_user\_creation.log)
❌ Problema attuale (blocco finale)
Nonostante il flusso OAuth appaia corretto:
1. **L’utente non compare in `Special:Users`**, né risulta registrato in modo persistente da MediaWiki.
2. I file di debug non vengono più scritti (es: `incoming_user_debug.json` è vuoto), anche se fino a poco prima funzionavano.
3. In alcuni tentativi recenti, **LinkedIn ha bloccato il flusso** reindirizzando su una pagina interna di errore: `challenge_global_internal_error`.
🧪 Possibili cause analizzate
🔹 1. LinkedIn blocca il flusso con errore interno ===
- Dopo numerosi tentativi ravvicinati, LinkedIn ha mostrato CAPTCHA e poi un errore generico con redirect su `/checkpoint/lg/login?errorKey=challenge_global_internal_error`.
- È possibile che il sistema LinkedIn consideri i tentativi come "anormali" da parte dello stesso IP server.
- Tuttavia, il login classico sul sito LinkedIn funziona, quindi l'account **non è bannato**.
🔹 2. Il file `create_mw_user_direct.php` non viene nemmeno raggiunto ===
- Potrebbe essere dovuto a un errore nella `curl_exec` finale nel callback.
- Oppure a **permessi Apache/PHP** sulla cartella `/oauth/`.
- Nessuna scrittura su `incoming_user_debug.json` è un forte indizio che l'esecuzione si ferma prima.
🔹 3. La fase di scrittura su MediaWiki fallisce silenziosamente
- Anche quando tutto sembra completarsi, l’utente non è visibile.
- MediaWiki potrebbe accettare la richiesta ma non completare il commit nel database.
🧰 Diagnostica svolta
- Test del singolo script `create_mw_user_direct.php` → funzionante in locale.
- Uso di `file_put_contents()` in vari punti → successivamente non più visibili.
- Logging attivo con timestamp → ora assente.
- Permessi `755` per i file PHP confermati.
📌 Prossimi tentativi suggeriti ==
1. **Verificare i permessi su tutta la cartella `/oauth/`**, specialmente se `www-data` ha accesso in scrittura.
2. **Inserire `var_dump()` o `echo` diagnostici in cima ai file** per vedere se si attivano realmente.
3. **Ripristinare uno script minimo** che scriva sempre qualcosa, anche senza passaggi LinkedIn, per confermare che la `curl` arrivi.
4. **Pulire cache LinkedIn** o aspettare 24-48h dopo l’errore `challenge_global_internal_error`.
5. **Verificare la variabile `client_id` e `client_secret`**: in uno degli ultimi tentativi era errata e ha mandato in confusione il flusso.
🧩 Conclusione provvisoria
Il sistema è quasi completo. La parte più difficile (flusso OAuth, access token, lettura dati utente) è superata con successo.
Resta da risolvere:
- La corretta chiamata finale a `create_mw_user_direct.php`
- La scrittura reale nel DB MediaWiki
- Il logging per capire il vero punto di blocco.
🔐 Nota finale
Si raccomanda di:
- Non toccare più i parametri dell'app LinkedIn finché non stabilizzati.
- Non effettuare più di 2-3 tentativi consecutivi in breve tempo.
- Non revocare l'app su [1](https://www.linkedin.com/psettings/permitted-services) per non perdere lo storico OAuth.
Una volta ripristinata la scrittura JSON o il log, potremo eseguire un nuovo ciclo completo e definitivo.
Pagina privata generata da ChatGPT su richiesta del fondatore di Masticationpedia, Gianni Frisardi.
Appendice
<?php
// linkedin-login.php
$client_id = 'TUO_CLIENT_ID';
$redirect_uri = 'https://staging.masticationpedia.org/oauth/linkedin-callback.php';
$scope = 'openid email profile';
$state = bin2hex(random_bytes(16));
$url = "https://www.linkedin.com/oauth/v2/authorization?response_type=code"
. "&client_id={$client_id}"
. "&redirect_uri=" . urlencode($redirect_uri)
. "&state={$state}"
. "&scope=" . urlencode($scope);
header("Location: $url");
exit;