[Résolu] Authentification HTTP

Bonjour,
Pour une API s’appuyant sur le plugin http, j’ai besoin d’authentifier des demandes de création ou de modification envoyées par POST.
Pour authentifier la demande, un commentaire indique qu’il faut utiliser « l’authentification HTTP que SPIP sait déjà gérer tout seul. » et lie la page wikipedia Authentification HTTP — Wikipédia

J’ai donc créé un rédacteur (autorisé à faire la modif) sur le site cible,
et j’ai agrémenté le POST curl de l’authentification http Basic qui devrait convenir…
mais ça ne semble pas le faire :
lorsque les autorisations sont vérifiées, le $qui n’est pas instancié,
c’est à dire que SPIP n’a pas utilisé l’authenticate http pour loger l’auteur décrit.

Ai je mal compris ?
Sur spip.net j’ai trouvé la doc de $GLOBALS[’ignore_auth_http’] qui désactive cette auth, mais rien sur l’auth elle même.
Comment faire fonctionner l’authentification http avec SPIP sur ce POST ?

Pour info, voici le code simplifié qui POSTe.

<?php
const _ORGANISATION_LOGIN = 'annonces.oasis';
const _ORGANISATION_MDP = 'annonces.oasis';

// 0 pas d'auth http 
// 1 avec CURLOPT_USERPWD 
// 2 avec CURLOPT_HTTPHEADER
$mode_auth = 2; 
$username = _ORGANISATION_LOGIN;
$password = _ORGANISATION_MDP;

$url = 'https://NDD/http.api/leformat/annonces';

// Données à envoyer (WIP format à enrichir et compléter)
$data = [
	'texte' => 'le texte le texte le texte le texte le texte le texte ',
	'titre' => 'le titre'
];
$data = http_build_query ($data); // url-encode
$ch = curl_init ($url);

switch ($mode_auth) {
	case 1:
		curl_setopt ($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
		curl_setopt ($ch, CURLOPT_USERPWD, "$username:$password");
		curl_setopt ($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
		break;
	case 2:
		$headers = array(
			'Content-Type:application/json',
			'Authorization: Basic '.base64_encode("$username:$password")
		);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
		break;
	default:
		break;
}

// curl_setopt ($ch, CURLOPT_HEADER, 1);       // pas bon là
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);       // réponse = chaîne
curl_setopt ($ch, CURLOPT_POST, true);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $data);

$response = curl_exec ($ch);

if (curl_errno ($ch)) {
	echo 'Erreur cURL : ' . curl_error ($ch);
} else {
	$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	echo "Code de statut HTTP : $httpCode\n<br>";
	echo "Réponse :<br>";
	if ($decoded = json_decode ($response)) {
		echo "<pre>".print_r($decoded, 1).'</pre>';
	}
	else {
		echo $response;
	}
}
curl_close ($ch);

Cette globale, comme l’indique la doc, concerne l’auth apache gérée un couple de fichiers htaccess/htpasswd, je ne suis pas certain que ça soit la chose que tu cherches.

Je pense que l’authenfication http exigée par htaccess/htpasswd est celle que permet l’entête Authorization: Basic dans une requête curl (autre moyen de loger une requête, comme le formulaire login/mdp http)

@Rastapopoulos peux tu préciser comment authentifier http une requête à l’api et bénéficier de ce que tu décris un peu comme un automagisme spip : « par défaut avec l’authentification HTTP que SPIP sait déjà gérer tout seul. » ?

A propos de $GLOBALS[’ignore_auth_http’] qui désactive l’auth http, @b_b a écrit : Cette globale, comme l’indique la doc, concerne l’auth apache gérée un couple de fichiers htaccess/htpasswd. Oui, je comprend cette globale comme désactivant l’automagisme SPIP décrit par @rasta que j’aimerais mettre en œuvre.

C’est censé marcher directement : si tu envoie une auth apache via login:pass dans l’URL ou via un header Authorization: Basic alors ils doivent arriver dans les deux globales
$_SERVER['PHP_AUTH_USER'] et $_SERVER['PHP_AUTH_PW']
et alors ils sont pris en compte pour identifier le user si ça correspond bien à un couple login/pass valide

Tout ça est en théorie, car encore faut-il que la config serveur soit correcte pour que les deux variables soient peuplées dans $_SERVER et donc il faut que tu debug pour trouver où est le problème chez toi si ça ne marche pas

1 « J'aime »

En effet, le serveur est en FPM/FastCGI (chez Gandi) et ne passe pas les variables PHP_AUTH_USER et PHP_AUTH_PW à PHP si bien que spip ne voit rien et ne fait rien.
J’ai ajouté ceci dans le .htaccess :

SetEnvIf Authorization .+ HTTP_AUTHORIZATION=$0

et les variables sont correctement passées.

SPIP apercevant ces variables vérifie alors si l’utilisateur de login PHP_AUTH_USER a bien le mot de passe PHP_AUTH_PW, et si tel est le cas, cet utilisateur est logé. Youpie.

Et cet automagisme est désormais documenté : Authentification http - Programmer avec SPIP 4

Je ne sais pas s’il faut mélanger la description de l’authentification basique HTTP (qui en serveur normal non bloquant est toujours récupéré par SPIP) et qui vaut en curl ou pas, n’importe quel outil faisant de l’auth basic, et la doc concernant .htpasswd qui n’a rien à voir, qui est la restriction d’accès propre à Apache, sans rapport ni avec SPIP ni avec PHP, mais que SPIP peut ou pas lire ou ignorer.

Il me semblait utile de rappeler comment basiquement on rencontre l’authentification http dans la vie, pour que « ça parle ». J’ai dissout cette introduction et du coup ça risque de rester abstrait pour un plus grand nombre de lecteurs… mais ça devrait désormais satisfaire ton attente !

Moi je suis encore plus perdu mais j’ai pas forcément tout pigé. Quand on utilise la variable de personnalisation « ignore_auth_http », est-ce que ça travaille sur TOUTES les auth http, MEME quand ya pas que fichier « .htpasswd » de Apache (qui sert à restreindre un site avec des login/pass en fichier à plat), ou bien est-ce que la variable est mal nommée et ne travaille QUE sue l’auth de Apache uniquement ?

Car dans la doc de la variable ça ne parle que des fichiers Apache. Alors qu’inversement, le remplissage automatique de l’auth SPIP avec l’auth HTTP Basic : ça ça marche même sans Apache et sans aucun rapport avec les fichiers .htpasswd.

Le critère déterminant n’est pas la présence d’un fichier .htpasswd mais, comme indiqué dans la nouvelle doc, la définition des variables PHP PHP_AUTH_USER et PHP_AUTH_PW, car SPIP les teste systématiquement pour loger l’auteur correspondant si yen a un qui matche – sauf si la variable « ignore_auth_http » est définie et true.

Pour cet automagisme, il faut et il suffit que ces variables soient définies. Et le fichier .htpasswd n’est qu’un des moyens de mettre en place une auth Basic et par exemple avec un curl et CURLOPT_HTTPAUTH CURLAUTH_BASIC il n’y a pas de fichier .htpasswd mais l’auth Basic est là quand même et assure la définition des variables PHP.

La description de la variable était donc incorrecte. J’ai simplifié : « Cette variable globale permet de dissocier l’authentification de SPIP de celle assurée par http au moyen d’une auth Basic. » et j’ai à nouveau complété, par contre, Authentification http - Programmer avec SPIP 4 puisque visiblement ça n’est pas inutile.

Ah voilà c’est ça que je savais pas, si cette variable ne valait pas que pour le fichier de Apache, et donc tu y réponds, du coup oui c’est bien plus clair maintenant merci.