Un proxy qui annule l'authentification, pourquoi pas ?

Première publication : 2011-01-21

Le contexte

Voilà une idée bien saugrenue, je vous l’accorde. Pour comprendre, voyons un peu le contexte.

Nous avons développé une application iPhone pour HotelHotel (le site sur lequel je travaille). Elle fonctionne en interrogeant notre API interne pour effectuer des recherches d’hôtels. L’API interroge nos partenaires compare les prix et compose une liste de résultats renvoyée à l’application iPhone.

Pour les hôtels, nous disposons de plusieurs photos, qui aident à se faire un avis sur les hôtels proposés. Ces photos sont gérées par nous mêmes, nous indiquons juste leur URL à l’application distante.

Jusqu’à ces derniers jours, nous stockions ces photos sur notre propre serveur, mais pour différentes raisons, nous les avons déportées vers le service Amazon S3. Il y a plein d’avantages à utiliser ce service : haute disponibilité des contenus, bande passante très importante, pas de soucis de croissance de l’espace utilisé… pour un coût très raisonnable.

Nous avons donc modifié les différentes parties de notre système pour que les fichiers soient placés sur Amazon S3 et les URL renvoyées aux navigateurs, application iPhone… soient celle sur Amazon S3 et plus sur notre serveur.

Le problème

Jusqu’ici tout va bien, ou presque. Nos différents sites web (public, admin…) fonctionnent bien, en lecture comme en écriture. Pa contre, l’appli iPhone plante et quitte dès qu’on veux charger une photo.

Après une séance de debuggage un peu déconcertante, on fini par trouver la source du problème. Pour bien comprendre, je rembobine un peu.

Pendant la phase de développement de l’appli iPhone, nous utilisions une version privée de l’API, sur un sous-domaine spécial, protégé par une authentification HTTP Basic. Juste avant la publication sur l’AppStore, nous avons changé le réglage pour pointer sur l’API de “production”, mais nous avons oublié d’enlever les en-têtes d’authentification.
On ne s’en est pas rendu compte car le serveur de production les ignorait. Il n’en attendait pas donc peu importe, il laissait tout passer.

Maintenant que les URL des images sont chez Amazon S3, et plus chez nous, ce sont leurs serveurs qui reçoivent les informations d’authentification. Manque de bol, leur serveur HTTP n’aime pas du tout les authentification de type HTTP Basic et il renvoi systématiquement une erreur 400 (Bad Request). Le contenu de la réponse est quant à lui une portion XML indiquant plus d’infos sur la requête, et c’est probablement ça qui fait planter l’appli. La bibliothèque utilisée n’arrive probablement pas à gérer un contenu XML au lieu d’un contenu image.

Corriger l’appli iPhone pour supprimer l’authentification est très simple, mais il faut ensuite soumettre une nouvelle version à Apple (plusieurs jours de délai pour la valider) puis attendre que l’extrême majorité de nos utilisateurs mettent à jour l’appli… Ce délai n’était pas envisageable.

La solution

Il m’est donc venue l’idée bizarre de mettre en place un moyen d’intercepter les URL demandées par l’iPhone, de les nettoyer des en-têtes d’authentification et de les transmettre à Amazon S3.

La mise en œuvre a été simple et rapide (grâce à l’aide de Grégory Colpart de Evolix). Nous avons créé un VirtualHost Apache sur un sous-domaine, dans lequel nous avons paramétré un reverse proxy. Toutes les requêtes envoyées à ce sous-domaines sont transmises de manière transparent à Amazon S3, et la directive RequestHeader supprime les en-têtes d’authentification.

Voilà la config du VirtualHost :

<VirtualHost *:80>
  ServerAdmin webmaster@example.com
  ServerName s3tmp.example.com

  ProxyRequests Off
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  ProxyPass / http://s3.example.com/
  ProxyPassReverse / http://s3.example.com/

  RequestHeader unset authorization
</VirtualHost>

NB : s3tmp.example.com est le sous-domaine du proxy, s3.example.com est un alias vers Amazon S3.