Mis à jour le mercredi 20 novembre 2013
  • Facile
Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Introduction du cours

Vous venez de finir de modifier votre script de connexion pour donner la possibilité aux utilisateurs de se souvenir de leur pseudo, et vous êtes persuadés d'avoir tout fait pour simplifier au maximum la tâche de vos membres ? Détrompez-vous : il existe un moyen pour les identifier d'un seul clic.

Dis, tu deviens pas un peu fou, là o_O ? Si on clique juste sur un bouton, tout le monde pourra se connecter sur mon site !

En fait, il y a une astuce : vos membres sont déjà identifiés sur d'autres sites plus connus que le vôtre, tels que Google, Facebook ou Windows Live, pour ne citer que les plus utilisés. Tous ces sites proposent une fonctionnalité intéressante : délivrer, avec l'accord de l'utilisateur, des données concernant leurs membres. Vous pouvez récupérer ces informations pour identifier vos membres.
De plus, vous pourrez proposer l'option « inscription-minute » : vous pourrez aller chercher les infos du visiteur directement dans son profil MSN ou Facebook !

Présentation de Janrain

JanRain

JanRain est un site qui permet de mettre en place gratuitement, rapidement et facilement un module permettant à vos membres de se connecter sur votre site en un clic !
De nombreux sites l'utilisent : vous pouvez voir la liste complète ici. Par exemple, le Site du Zéro l'utilisait :

Lien de connexion avec un compte externe du Site du Zéro

Lorsqu'on clique sur les petites icônes, une fenêtre apparaît :

Fenêtre de connexion pour un compte externe sur le Site du Zéro

Vous avez le choix entre plusieurs fournisseurs OpenID. Un fournisseur est un gros site, comme Windows Live, Google, Facebook... Il permet à ses membres de délivrer, avec leur accord, des informations les concernant. Si vous êtes déjà connectés sur un de ces fournisseurs, on vous propose directement de vous loguer sur le SdZ :

Fenêtre de connexion lorsque vous êtes déjà logué

Avantages

  • Connexion et inscription en un clic !

  • Support de nombreux fournisseurs OpenID.

  • Simple à mettre en place.

Inconvénients

  • Le temps de chargement est très long : le visiteur est d'abord redirigé vers le site de Janrain, puis vers le fournisseur, puis il retourne sur Janrain... Bref, c'est parfois plus rapide de se connecter directement :lol:

  • Vous ne pouvez pas personnaliser l'interface utilisateur pour l'adapter a votre site.

  • Votre site dépend de JanRain : si un problème technique survient, ou pire, si cette entreprise disparaît, votre script ne fonctionnera plus.

Comment ça marche ?

Schéma de fonctionnement de JanRain
  • Étape 1 : l'utilisateur clique sur une des icônes de fournisseurs sur votre site.

  • Étape 2 : JanRain redirige le visiteur vers le site du fournisseur pour l'authentification.

  • Étape 3 : le fournisseur renvoie des infos à JanRain, qui les sauvegarde dans sa BDD.

  • Étape 4 : votre site envoie une requête vers la BDD de JanRain qui lui renvoie des infos sur le membre en question.

Convaincus ? Alors c'est parti ! :pirate:

La base du système

Lorsqu'un membre tente de se connecter avec un site externe, ce site retourne automatiquement un ID et une adresse internet. Il est possible de récupérer certaines informations sur le membre, telles que son adresse e-mail, son avatar, etc...
Par exemple, voici un lien pour Google (j'ai choisi un id au hasard) :

https://www.google.com/accounts/o8/id?id=fbf83cgfryqm8f73nqzf8rng3irxmg43qmf

On appelle ce lien l'identifier. On ne va pas utiliser l'ID, car deux utilisateurs différents peuvent avoir un ID similaire, l'un étant sur Google, l'autre sur Facebook. En revanche, l'identifier est unique, quel que soit le site externe.
On peut donc utiliser l'identifier pour lier un compte externe à un compte sur votre site : ainsi, lorsque un utilisateur se connecte avec Janrain, on vérifiera si l'identifier est déjà stocké dans la BDD.
Par exemple, la table membres :

id

pseudo

mail

identifier

1

BrianMan692

brianman692@gmail.com

https://www.google.com/accounts/o8/id? [...] ng3irxmg43qmf

2

$imon

simon@gmail.com

https://www.google.com/accounts/o8/id? [...] ng3irxmg53qmg

On a rajouté une colonne identifier pour mémoriser le lien renvoyé par la BDD de JanRain. Il servira à stocker l'identifier lors de l'inscription et à le comparer avec celui renvoyé par JanRain lors de la connexion.
Nous allons créer une page pour gérer l'inscription avec JanRain, on va l'appeler inscriptionjanrain.php. On aura besoin d'en créer une autre pour la connexion : connexionjanrain.php.

Étape 1 : ajoutez des fournisseurs !

Vous l'avez bien vu, lorsque la boîte de connexion est affichée, on a le choix entre plusieurs fournisseurs.
Tout d'abord, vous devez créer un compte sur cette page. Si vous ne voulez pas payer, il y a une version gratuite limitée : cliquez sur « Sign up » pour vous inscrire (oui, JanRain n'est disponible qu'en anglais :euh: ). Et... une fenêtre comme sur le SdZ s'ouvre ! Eh oui, le site de JanRain lui-même utilise ses propres services ! Si vous possédez déjà un compte OpenID, il suffit de cliquer sur son icône. Sinon, il est temps de s'inscrire sur un des fournisseurs !
Il vous suffit de remplir les informations demandées pour vous inscrire. On vous demandera le nom de votre application, vous pouvez mettre le nom de votre site web (cela n'a pas une grande importance).
Vous vous retrouvez ensuite devant le panneau de configuration de votre application :
Panneau de configuration
Pour commencer à modeler votre nouvelle application, cliquez sur « Sign-in for Web », dans le menu « Deployment » :

Menu deployment -> sign-in for Web

Vous vous retrouvez face à un autre formulaire :

Formulaire sign-in for Web

Dans la première liste, vous pouvez choisir d'avoir le code soit pour ouvrir une fenêtre (« modal »), soit pour insérer un cadre (« embedded »).

Pourquoi certaines fonctionnalités sont-elles grisées ?

Janrain est un service payant, et certaines options sont réservées aux membres « Pro ». Les options grisées sont juste la dans le but de vous faire saliver !

Pour ajouter des fournisseurs, cliquez sur la liste « Providers » en bas a gauche, puis faites un glisser-déposer d'un fournisseur vers la grille.

Tous les fournisseurs accompagnés de l'icône

Icône pour les fournisseurs nécessitant une configuration

sur leur droite demandent des paramètres spéciaux. Les autres peuvent s'ajouter en un seul clic sans pré-requis (un seul glisser-déplacer en l'occurrence ;) ).

Pour Facebook

Vous devez en premier lieu être inscrits sur Facebook. Connectez-vous et allez à l'adresse : http://www.facebook.com/developers/. Cliquez sur « Accepter », puis sur

Bouton Créer une application de Facebook

en haut à droite. Donnez le nom que vous voulez à votre application, cela n'a pas d'importance. N'oubliez pas de cocher « J'accepte les conditions d'utilisation » et validez.
Du côté du site de JanRain, il faut cliquer deux fois sur « Next ». Une page s'affiche ensuite avec différents renseignements. Faites un copier-coller de :

  • Clé API vers API key (Facebook => JanRain) ;

  • Secret vers Application Secret.

Cochez la case « Yes! I want to receive my users email addresses. » pour recevoir les adresses e-mail des membres qui vont se connecter sur votre site avec Facebook.

Pour Windows Live ID

Pour Windows Live ID, c'est un peu plus compliqué. Vous devez tout d'abord posséder un compte Windows Live. Lorsque vous faites un glisser-déplacer avec Windows Live ID, on vous demande une Privacy Policy URL. C'est la page vers la politique de confidentialité de votre site Web.
Ensuite, allez sur la page de création d'une application Windows Live. Connectez-vous à l'aide de votre identifiant Windows Live. Vous vous retrouvez devant une page en anglais ( :-° ) ; le système est le même qu'avec Facebook.
Je vous laisse remplir les deux premiers champs (titre et langue), vous avez l'habitude maintenant. ;)
Vous pouvez ensuite valider en cliquant sur « I accept », vous devez arriver sur une page de confirmation :

Page de confirmation

Revenez sur le site de JanRain, cliquez sur « Next » jusqu'à la troisième étape. On vous fournit un renseignement : Return URL. Revenez sur le site de Windows Live, cliquez sur « Application Settings Page » puis « API Settings » :

Menu API settings

Il faut maintenant entrer Return URL dans le champ « Redirect domain ».

API settings

Cliquez ensuite sur « Next » sur le site de JanRain. Faites un copier-coller de « Application Id » et de « Secret Key » dans le formulaire qui s'affiche.
Cliquez sur « Save » pour enregistrer les infos.

Pour les autres fournisseurs

La manipulation est quasiment la même que pour Facebook, ou aucune manipulation n'est requise. Je vous laisse vous débrouiller pour le reste des fournisseurs. ;)

Étape 2 : intégrer JanRain dans votre site

Le code xHTML et JavaScript à insérer dans vos pages

Pour intégrer Janrain dans votre site, cliquez sur « Get the Code » :

Get the code

Le site vous donne alors un code JavaScript et un autre en HTML. Ils devraient ressembler à ceci :

<script type="text/javascript">
(function() {
    if (typeof window.janrain !== 'object') window.janrain = {};
    window.janrain.settings = {};
    
    janrain.settings.tokenUrl = '__REPLACE_WITH_YOUR_TOKEN_URL__';

    function isReady() { janrain.ready = true; };
    if (document.addEventListener) {
      document.addEventListener("DOMContentLoaded", isReady, false);
    } else {
      window.attachEvent('onload', isReady);
    }

    var e = document.createElement('script');
    e.type = 'text/javascript';
    e.id = 'janrainAuthWidget';

    if (document.location.protocol === 'https:') {
      e.src = 'https://rpxnow.com/js/lib/user/engage.js';
    } else {
      e.src = 'http://widget-cdn.rpxnow.com/js/lib/user/engage.js';
    }

    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(e, s);
})();
</script>
<a class="janrainEngage" href="#">Sign-In</a>

Le premier code est à insérer dans la balise <body></body> dans votre page de connexion habituelle. Il est conseillé de le mettre juste avant </body>. Le second code est un lien : celui qui ouvrira la fenêtre de connexion. Vous pouvez le mettre n'importe où dans votre balise <body></body>.

Il faut rajouter un paramètre après janrain.settings.tokenUrl = '__REPLACE_WITH_YOUR_TOKEN_URL__'; :

janrain.settings.tokenUrl = 'http://unsite.com/connexionjanrain.php';

Il correspond a la page vers laquelle le visiteur sera redirigé après authentification, nous la coderons plus loin dans le tutoriel.

Vous remarquerez que l'interface de connexion de Janrain est elle aussi en anglais. Pour pouvoir personnaliser la fenêtre et changer la langue, il vous faudra... Payer. :(

Configurer JanRain

Entrez dans les paramètres de votre application en cliquant sur « Application settings » dans le menu « Deployment » :

Menu deployment -> application settings

Dans le premier champ, vous pouvez entrer les domaines sur lesquels elle pourra être utilisée. Si l'adresse de votre site est http://unsite.com/, vous pouvez mettre unsite.com. Si vous avez des sous-domaines et que vous voulez que votre application soit aussi utilisable dessus, vous pouvez entrer unsite.com et *.unsite.com.

JanRain est configuré pour ne renvoyer qu'une seule fois les informations sur le membre. Or, nous aurons besoin d'actualiser la page pour pouvoir demander au visiteur certaines infos.
On va donc modifier cela : dans la section « Migrations », il faut désactiver l'utilisation unique des token (« One-time use auth_info tokens ») :

One-time use auth_info tokens

Étape 3 : l'inscription

Nous allons ici coder la page inscriptionjanrain.php, qui gère l'inscription avec un compte externe.

Réfléchissons...

On va récupérer les informations du membre avec JanRain. Il suffira alors de les enregistrer dans la BDD s'il n'en manque pas (quelques fournisseurs ne fournissent pas l'e-mail ou le pseudo de leur membre). S'il n'y a pas les données minimales, on les demandera au visiteur par un formulaire.
Un bon schéma vaut mieux qu'un long discours :lol: :

Image utilisateur

Codons !

Cliquez sur « Call the API » :

Call the API

Vous avez le script de base à cette adresse : http://gist.github.com/291396.
Le voici (les commentaires ont été traduits en français pour une meilleure compréhension du code) :

<?php
// Ici, un script basique pour recevoir les données des fournisseurs (requiert PHP 5 ou plus)
// Vous devez avoir installé CURL HTTP fetching library

$JanRainApiKey = 'REMPLACEZ_CE_TEXTE_AVEC_VOTRE_CLEF_API';  

if(isset($_POST['token'])) { // Si l'utilisateur tente de se connecter avec JanRain

  /* ÉTAPE 1 : récupérer le paramètre token */
  $token = $_POST['token'];

  /* ÉTAPE 2 : utiliser le token pour envoyer une requête vers le serveur de JanRain, qui interrogera à son tour le fournisseur */
  $post_data = array('token' => $_POST['token'],
                     'apiKey' => $JanRainApiKey,
                     'format' => 'json'); 

  $curl = curl_init(); // Initialisation
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Retourne le résultat du transfert au lieu de l'afficher
  curl_setopt($curl, CURLOPT_URL, 'https://rpxnow.com/api/v2/auth_info'); // On définit l'URL cible à récupérer
  curl_setopt($curl, CURLOPT_POST, true); // On dit à PHP de faire un HTTP POST (comme pour les formulaires)
  curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); // Données à fournir par HTTP POST
  curl_setopt($curl, CURLOPT_HEADER, false); // On dit de ne pas renvoyer l'en-tête dans la valeur de retour
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // On ne vérifie pas le certificat SSL
  $raw_json = curl_exec($curl); // On exécute la requête
  curl_close($curl); // On ferme la connexion


  /* ÉTAPE 3 : décoder la réponse Json */
  $auth_info = json_decode($raw_json, true);

  if ($auth_info['stat'] == 'ok') { // Si tout est OK
  
    /* ÉTAPE 4 : récupérer les infos à partir de la réponse */
    $profile = $auth_info['profile']; // Les infos sur le membre
    $identifier = $profile['identifier']; // Le lien

    if (isset($profile['photo']))  { // Avatar
      $photo_url = $profile['photo'];
    }

    if (isset($profile['displayName']))  { // Nom à afficher
      $displayName = $profile['displayName'];
    }

    if (isset($profile['email']))  { // E-mail
      $email = $profile['email'];
    }

    /* ÉTAPE 5 : utilisez l'identifier pour identifier les utilisateurs dans votre site
     * Nous allons revenir sur cette partie un peu plus tard...
     */

  } else { /* Une erreur est survenue */
     // On affiche l'erreur
     echo 'Une erreur est survenue : ' . $auth_info['err']['msg'];
  }
}
?>

Pensez à modifier la valeur de $JanRainApiKey avec celle fournie dans ce cadre :

Image utilisateur

Pour ceux qui ne connaissent pas cURL, voici un peu de lecture :

Citation : Manuel PHP

PHP supporte libcurl, une bibliothèque créée par Daniel Stenberg, qui vous permet de vous connecter et de communiquer avec différents types de serveurs, et ce, avec différents types de protocoles. libcurl supporte actuellement les protocoles http, https, ftp, gopher, telnet, DICT, file et LDAP. libcurl supporte également les certificats HTTPS, HTTP POST, HTTP PUT, le téléchargement FTP (ceci pouvant également être effectué via l'extension ftp de PHP), les formulaires de téléchargement HTTP, les serveurs mandataires (proxy), les cookies et l'identification utilisateur/mot de passe.

Si cURL n'est pas installé, vous aurez ce message d'erreur :

Citation : Erreur PHP

Fatal error: Call to undefined function curl_init() in connexionjanrain.php on line 17

Pour l'installer, si vous êtes en local, il faut activer le module cURL : Icône wamp > PHP > Extensions PHP > php_curl.
Puis il faut redémarrer wamp, si ce n'est pas fait pas automatiquement (l'icône change de couleur).
Sur serveur, un paquet de cURL doit exister pour votre distribution Linux (par exemple, voir ici pour Ubuntu). Voici le site de cURL, ou vous devrez trouver votre bonheur dans la section "Downloads" : http://curl.haxx.se/. ;)

Dis, c'est bien beau tout ça, mais comment inscrire les membres maintenant ?

Tout d'abord, se connecter à sa BDD (placez ce code à la place de l'étape 5 du code ci-dessus) :

<?php
session_start(); // On démarre les sessions
// Connexion à la BDD
$PARAM_hote='localhost'; // Le chemin vers le serveur
$PARAM_port='3306';
$PARAM_nom_bd='monsite'; // Le nom de votre base de données
$PARAM_utilisateur='root'; // Nom d'utilisateur pour se connecter
$PARAM_mot_passe=''; // Mot de passe de l'utilisateur pour se connecter
try {
	$connexion = new PDO('mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
} catch(Exception $e) {
	echo 'Erreur : '.$e->getMessage().'<br />';
	echo 'N° : '.$e->getCode();
}
$connexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // Lance une alerte à chaque requête échouée
?>

Ensuite, vérifier que le membre n'est pas déjà inscrit :

<?php
if (isset($_GET['JanRain_inscrire'])) { // Si le visiteur veut s'inscrire avec JanRain
	$nombreResultats = $connexion->query('SELECT COUNT(*) FROM membres WHERE identifier = \''.$identifier.'\'')->fetchColumn(); // On vérifie si le visiteur n'est pas déjà inscrit
	if ($nombreResultats == 1) {
		$message = '<p>Vous êtes déjà inscrit !</p><form action="./connexionjanrain.php" method="post"><input type="hidden" name="token" value="'.$token.'"/><input type="submit" value="Me connecter"/></form>'; // Message
	}
?>

Sinon, on vérifie qu'aucun membre n'a la même adresse e-mail que le visiteur.

<?php
	else {
		if ((isset($displayName) OR isset($_POST['pseudo'])) AND (isset($email) OR isset($_POST['email']))) { // Si on a toutes les infos
			$nombreResultats = $connexion->query('SELECT COUNT(*) FROM membres WHERE mail = \''.$email.'\'')->fetchColumn(); // On vérifie si un membre n'a pas cet e-mail
			if ($nombreResultats == 1) {
				$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\'');
				$donnees = $query->fetch(PDO::FETCH_ASSOC);
				$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, êtes-vous bien <strong>'.$donnees['pseudo'].'</strong> ? Cette question ne vous sera plus posée à l\'avenir.</p>
				<form action="./connexionjanrain.php?JanRain_lier">
				<input type="hidden" name="token" value="'.$token.'"/>
				<input type="submit" value="Oui"/> <a href="./connexion.php"><input type="button" value="Non"/></a>
				</form>'; // Message
			}
?>

Si tout est O.K., on inscrit le visiteur :

<?php
			else {
				if (isset($_POST['pseudo']))
					$displayName = $_POST['pseudo'];
				if (isset($_POST['email']))
					$email = $_POST['email'];
				$query = $connexion->prepare('INSERT INTO membres (id,pseudo,mail,identifier) VALUES (\'\',?,?,?)'); // On enregistre les infos
				$query->execute(array($displayName, $email, $identifier));
				$_SESSION['pseudo'] = $donnees['pseudo']; // On connecte le membre
				$_SESSION['id'] = $donnees['id'];
				$message = '<p>Vous avez bien été inscrit !
				<a href="./index.php">Cliquez ici</a> 
				pour revenir à la page d\'accueil</p>'; // Message
			}
		}
?>

S'il n'y a pas assez d'infos, on les demande :

<?php
		} else { // Pas assez d'infos : on les demande
			if (!isset($displayName))
				$displayName = '';
			if (!isset($email))
				$email = '';
			$message = '<p>Veuillez renseigner les champs ci-dessous pour vous inscrire :</p>
			<form action="./inscriptionjanrain.php" method="post">
			<input type="hidden" name="token" value="'.$token.'"/>
			Pseudo : <input type="text" name="pseudo" value="'.$displayName.'"/>
			E-mail : <input type="text" name="email" value="'.$email.'"/>
			<input type="submit" value="M\'inscrire !"/>
			</form>';
		}
	}
}
?>

Ouf !
Voici le code complet :

<?php
// Ici, un script basique pour recevoir les données des fournisseurs (requiert PHP 5 ou plus)
// Vous devez avoir installé CURL HTTP fetching library

$JanRainApiKey = 'REMPLACEZ_CE_TEXTE_AVEC_VOTRE_CLEF_API';  

if(isset($_POST['token'])) { // Si l'utilisateur tente de se connecter avec JanRain

	/* ÉTAPE 1 : récupérer le paramètre token */
	$token = $_POST['token'];

	/* ÉTAPE 2 : utiliser le token pour envoyer une requête vers le serveur de JanRain, qui interrogera à son tour le fournisseur */
	$post_data = array('token' => $_POST['token'],
		'apiKey' => $JanRainApiKey,
		'format' => 'json'); 

	$curl = curl_init(); // Initialisation
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Retourne le résultat du transfert au lieu de l'afficher
	curl_setopt($curl, CURLOPT_URL, 'https://rpxnow.com/api/v2/auth_info'); // On définit l'URL cible à récupérer
	curl_setopt($curl, CURLOPT_POST, true); // On dit à PHP de faire un HTTP POST (comme pour les formulaires)
	curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); // Données à fournir par HTTP POST
	curl_setopt($curl, CURLOPT_HEADER, false); // On dit de ne pas renvoyer l'en-tête dans la valeur de retour
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // On ne vérifie pas le certificat SSL
	$raw_json = curl_exec($curl); // On exécute la requête
	curl_close($curl); // On ferme la connexion

	/* ÉTAPE 3 : décoder la réponse Json */
	$auth_info = json_decode($raw_json, true);

	if ($auth_info['stat'] == 'ok') { // Si tout est OK
  
		/* ÉTAPE 4 : récupérer les infos à partir de la réponse */
		$profile = $auth_info['profile']; // Les infos sur le membre
		$identifier = $profile['identifier']; // Le lien

		if (isset($profile['photo']))  { // Avatar
			$photo_url = $profile['photo'];
		}

		if (isset($profile['displayName']))  { // Nom à afficher
			$displayName = $profile['displayName'];
		}

		if (isset($profile['email']))  { // E-mail
			$email = $profile['email'];
		}

		session_start(); // On démarre les sessions
		// Connexion à la BDD
		$PARAM_hote='localhost'; // Le chemin vers le serveur
		$PARAM_port='3306';
		$PARAM_nom_bd='monsite'; // Le nom de votre base de données
		$PARAM_utilisateur='root'; // Nom d'utilisateur pour se connecter
		$PARAM_mot_passe=''; // Mot de passe de l'utilisateur pour se connecter
		try {
			$connexion = new PDO('mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
		} catch(Exception $e) {
			echo 'Erreur : '.$e->getMessage().'<br />';
			echo 'N° : '.$e->getCode();
		}
		$connexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // Lance une alerte à chaque requête échouée

		$nombreResultats = $connexion->query('SELECT COUNT(*) FROM membres WHERE identifier = \''.$identifier.'\'')->fetchColumn(); // On vérifie si le visiteur n'est pas déjà inscrit
		if ($nombreResultats == 1) {
			$message =  '<p>Vous êtes déjà inscrit !</p><form action="./connexionjanrain.php" method="post"><input type="hidden" name="token" value="'.$token.'"/><input type="submit" value="Me connecter"/></form>'; // Message
		} else {
			if ((isset($displayName) OR isset($_POST['pseudo'])) AND (isset($email) OR isset($_POST['email']))) { // Si on a toutes les infos
				$nombreResultats = $connexion->query('SELECT COUNT(*) FROM membres WHERE mail = \''.$email.'\'')->fetchColumn(); // On vérifie si un membre n'a pas cet e-mail
				if ($nombreResultats == 1) {
					$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\'');
					$donnees = $query->fetch(PDO::FETCH_ASSOC);
					$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, êtes-vous bien <strong>'.$donnees['pseudo'].'</strong> ? Cette question ne vous sera plus posée à l\'avenir.</p>
					<form action="./connexionjanrain.php?JanRain_lier">
					<input type="hidden" name="token" value="'.$token.'"/>
					<input type="submit" value="Oui"/> <a href="./connexion.php"><input type="button" value="Non"/></a>
					</form>'; // Message
				} else {
					if (isset($_POST['pseudo']))
						$displayName = $_POST['pseudo'];
					if (isset($_POST['email']))
						$email = $_POST['email'];
					$query = $connexion->prepare('INSERT INTO membres (id,pseudo,mail,identifier) VALUES (\'\',?,?,?)'); // On enregistre les infos
					$query->execute(array($displayName, $email, $identifier));
					$_SESSION['pseudo'] = $donnees['pseudo']; // On connecte le membre
					$_SESSION['id'] = $donnees['id'];
					$message = '<p>Vous avez bien été inscrit !
					<a href="./index.php">Cliquez ici</a> 
					pour revenir à la page d\'accueil</p>'; // Message
				}
			} else { // Pas assez d'infos : on les demande
				if (!isset($displayName))
					$displayName = '';
				if (!isset($email))
					$email = '';
				$message = '<p>Veuillez renseigner les champs ci-dessous pour vous inscrire :</p>
				<form action="./inscriptionjanrain.php" method="post">
				<input type="hidden" name="token" value="'.$token.'"/>
				Pseudo : <input type="text" name="pseudo" value="'.$displayName.'"/>
				E-mail : <input type="text" name="email" value="'.$email.'"/>
				<input type="submit" value="M\'inscrire !"/>
				</form>';
			}
		}

	} else { /* Une erreur est survenue */
		// On affiche l'erreur
		echo 'Une erreur est survenue : ' . $auth_info['err']['msg'];
	}
}
echo $message;
?>

Étape 4 : la connexion

Nous allons ici coder la page connexionjanrain.php, elle permet au visiteur de se connecter avec un compte externe.

Réfléchissons...

On pourra alors voir si l'identifier est déjà stocké dans la BDD ou non à chaque connexion avec JanRain. S'il l'est, on a juste à identifier le membre en question. Sinon, on vérifiera si l'adresse e-mail du visiteur est déjà enregistrée dans la BDD. Si elle l'est, on demande la confirmation au membre, sinon, on lui demande de se connecter « à l'ancienne ». Une fois connecté, on sauvegardera le lien dans la BDD, sur la même ligne que ce membre.
Voici un petit schéma qui permet de s'y retrouver plus simplement :

Shema de fonctionnement de la connexion avec JanRain

Codons !

Tout d'abord, il faut vérifier si l'identifier est déjà stocké dans votre BDD (placez ce code à la place de l'étape 5 du code de base, dans connexionjanrain.php) :

<?php
// On compte le nombre de membres ayant pour identifier celui retourné par JanRain
$nombreResulat = $connexion->query('SELECT COUNT(*) FROM membres WHERE identifier = \''.$identifier.'\'')->fetchColumn();
if ($nombreResulat == 1) { // S'il y a un résultat
	$query = $connexion->query('SELECT pseudo, id FROM membres WHERE identifier = \''.$identifier.'\'');
	$donnees = $query->fetch(PDO::FETCH_ASSOC); // On met en forme la réponse de la BDD
?>

Les commentaires devraient suffire pour comprendre le code.
Ensuite, il faut identifier le membre. Placez ce code juste à la suite de celui ci-dessus :

<?php
	$_SESSION['pseudo'] = $donnees['pseudo'];
	$_SESSION['id'] = $donnees['id'];
	$message = '<p>Bienvenue '.htmlspecialchars($donnees['pseudo']).', 
	vous êtes maintenant connecté !</p>
	<p>Cliquez <a href="./index.php">ici</a> 
	pour revenir à la page d\'accueil</p>';
}
?>

On définit ici les différentes variables de session.
Si l'identifier n'est pas enregistré et que le fournisseur a retourné un e-mail, on vérifie si l'e-mail est dans la BDD. Si oui, on demande la confirmation :

<?php
} elseif (isset($email)) {
	// On compte le nombre de membres ayant pour e-mail celui retourné par JanRain
	$nombreResulat = $connexion->query('SELECT COUNT(*) FROM membres WHERE mail = \''.$email.'\'')->fetchColumn();
	if ($nombreResulat == 1) { // S'il y a un résultat
		$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\'');
		$donnees = $query->fetch(PDO::FETCH_ASSOC);
		$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, êtes-vous bien <strong>'.$donnees['pseudo'].'</strong> ? Cette question ne vous sera plus posée à l\'avenir.</p>
		<form action="?JanRain_lier">
		<input type="hidden" name="token" value="'.$token.'"/>
		<input type="submit" value="Oui"/> <a href="./connexion.php"><input type="button" value="Non"/></a>
		</form>';
	}
?>

Sinon, on demande au membre de se connecter normalement :

<?php
	else { // S'il n'y a pas de résultat
		$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, nous vous demandons de vous connecter avec votre compte sur ce site. Cette question ne vous sera plus posée à l\'avenir.</p>
		<form action="?JanRain_lier" method="post">
		<input type="text" name="pseudo"/>
		<input type="password" name="password"/>
		<input type="hidden" name="token" value="'.$token.'"/>
		<input type="submit" value="Valider"/>
		</form>'; // Formulaire de connexion
	}
} else { // S'il n'y a pas d'e-mail
	$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, nous vous demandons de vous connecter avec votre compte sur ce site. Cette question ne vous sera plus posée à l\'avenir.</p>
	<form action="?JanRain_lier" method="post">
	<input type="text" name="pseudo"/>
	<input type="password" name="password"/>
	<input type="hidden" name="token" value="'.$token.'"/>
	<input type="submit" value="Valider"/>
	</form>
	</div>'; // Formulaire de connexion
}
?>

Enfin !
Pour la suite, il faut vérifier si le membre demande de lier un compte :

<?php
if (isset($_GET['JanRain_lier'])) { // Si on demande de lier un compte
	if (isset($_SESSION['id'])) { // Si le membre s'est connecté
		$query = $connexion->prepare('UPDATE membres SET identifier = ? WHERE id = ?'); // On change l'identifier du membre dans la BDD
		$req->execute(array($identifier, $_SESSION['id']));
		echo '<p>Le compte a bien été lié. Vous n\'avez qu\'à cliquer sur un bouton pour vous connecter !</p>'; // Message
	} else { // Sinon, il n'est pas connecté
		$query = $connexion->prepare('UPDATE membres SET identifier = ? WHERE mail = ?'); // On modifie la table
		$req->execute(array($identifier, $email));
		$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\''); // On récupère les données concernant le membre
		$donnees = $query->fetch(PDO::FETCH_ASSOC);
		$_SESSION['pseudo'] = $donnees['pseudo']; // On connecte le membre
		$_SESSION['id'] = $donnees['id'];
		$message = '<p>Le compte a bien été lié. Vous n\'avez qu\'à cliquer sur un bouton pour vous connecter !</p>'; // Message
	}
}
?>

C'est tout !
Voici le code complet :

<?php
// Ici, un script basique pour recevoir les données des fournisseurs (requiert PHP 5 ou plus)
// Vous devez avoir installé CURL HTTP fetching library

$JanRainApiKey = 'REMPLACEZ_CE_TEXTE_AVEC_VOTRE_CLEF_API';  

if(isset($_POST['token'])) { // Si l'utilisateur tente de se connecter avec JanRain

	/* ÉTAPE 1 : récupérer le paramètre token */
	$token = $_POST['token'];

	/* ÉTAPE 2 : utiliser le token pour envoyer une requête vers le serveur de JanRain, qui interrogera à son tour le fournisseur */
	$post_data = array('token' => $_POST['token'],
		'apiKey' => $JanRainApiKey,
		'format' => 'json'); 

	$curl = curl_init(); // Initialisation
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // Retourne le résultat du transfert au lieu de l'afficher
	curl_setopt($curl, CURLOPT_URL, 'https://rpxnow.com/api/v2/auth_info'); // On définit l'URL cible à récupérer
	curl_setopt($curl, CURLOPT_POST, true); // On dit à PHP de faire un HTTP POST (comme pour les formulaires)
	curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); // Données à fournir par HTTP POST
	curl_setopt($curl, CURLOPT_HEADER, false); // On dit de ne pas renvoyer l'en-tête dans la valeur de retour
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // On ne vérifie pas le certificat SSL
	$raw_json = curl_exec($curl); // On exécute la requête
	curl_close($curl); // On ferme la connexion


	/* ÉTAPE 3 : décoder la réponse Json */
	$auth_info = json_decode($raw_json, true);

	if ($auth_info['stat'] == 'ok') { // Si tout est OK
  
		/* ÉTAPE 4 : récupérer les infos à partir de la réponse */
		$profile = $auth_info['profile']; // Les infos sur le membre
		$identifier = $profile['identifier']; // Le lien

		if (isset($profile['photo']))  { // Avatar
			$photo_url = $profile['photo'];
		}

		if (isset($profile['displayName']))  { // Nom à afficher
			$displayName = $profile['displayName'];
		}

		if (isset($profile['email']))  { // E-mail
			$email = $profile['email'];
		}

		session_start(); // On démarre les sessions
		// Connexion à la BDD
		$PARAM_hote='localhost'; // Le chemin vers le serveur
		$PARAM_port='3306';
		$PARAM_nom_bd='monsite'; // Le nom de votre base de données
		$PARAM_utilisateur='root'; // Nom d'utilisateur pour se connecter
		$PARAM_mot_passe=''; // Mot de passe de l'utilisateur pour se connecter
		try {
			$connexion = new PDO('mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
		} catch(Exception $e) {
			echo 'Erreur : '.$e->getMessage().'<br />';
			echo 'N° : '.$e->getCode();
		}
		$connexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); // Lance une alerte à chaque requête échouée

		// On compte le nombre de membres ayant pour identifier celui retourné par JanRain
		$nombreResulat = $connexion->query('SELECT COUNT(*) FROM membres WHERE identifier = \''.$identifier.'\'')->fetchColumn();
		if ($nombreResulat == 1) { // S'il y a un résultat
			$query = $connexion->query('SELECT pseudo, id FROM membres WHERE identifier = \''.$identifier.'\'');
			$donnees = $query->fetch(PDO::FETCH_ASSOC); // On met en forme la réponse de la BDD
			$_SESSION['pseudo'] = $donnees['pseudo'];
			$_SESSION['id'] = $donnees['id']; // On identifie le membre
			$message = '<p>Bienvenue '.htmlspecialchars($donnees['pseudo']).', 
			vous êtes maintenant connecté !</p>
			<p><a href="./index.php">Cliquez ici</a> 
			pour revenir à la page d\'accueil</p>'; // Message
		} elseif (isset($email)) {
			// On compte le nombre de membres ayant pour e-mail celui retourné par JanRain
			$nombreResulat = $connexion->query('SELECT COUNT(*) FROM membres WHERE mail = \''.$email.'\'')->fetchColumn();
			if ($nombreResulat == 1) { // S'il y a un résultat
				$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\'');
				$donnees = $query->fetch(PDO::FETCH_ASSOC);
				$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, êtes-vous bien <strong>'.$donnees['pseudo'].'</strong> ? Cette question ne vous sera plus posée à l\'avenir.</p>
				<form action="?JanRain_lier">
				<input type="hidden" name="token" value="'.$token.'"/>
				<input type="submit" value="Oui"/> <a href="./connexion.php"><input type="button" value="Non"/></a>
				</form>';
			} else { // S'il n'y a pas de résultat
				$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, nous vous demandons de vous connecter avec votre compte sur ce site. Cette question ne vous sera plus posée à l\'avenir.</p>
				<form action="?JanRain_lier" method="post">
				<input type="text" name="pseudo"/>
				<input type="password" name="password"/>
				<input type="hidden" name="token" value="'.$token.'"/>
				<input type="submit" value="Valider"/>
				</form>'; // Formulaire de connexion
			}
		} else { // S'il n'y a pas d'e-mail
			$message = '<p>Vous pouvez vous connecter avec un compte externe en cliquant seulement sur un bouton ! Seulement, nous vous demandons de vous connecter avec votre compte sur ce site. Cette question ne vous sera plus posée à l\'avenir.</p>
			<form action="?JanRain_lier" method="post">
			<input type="text" name="pseudo"/>
			<input type="password" name="password"/>
			<input type="hidden" name="token" value="'.$token.'"/>
			<input type="submit" value="Valider"/>
			</form>'; // Formulaire de connexion
		}

		if (isset($_GET['JanRain_lier'])) { // Si on demande de lier un compte
			if (isset($_SESSION['id'])) { // Si le membre s'est connecté
				$query = $connexion->prepare('UPDATE membres SET identifier = ? WHERE id = ?'); // On change l'identifier du membre de la BDD
				$req->execute(array($identifier, $_SESSION['id']));
				echo '<p>Le compte a bien été lié. Vous n\'avez qu\'à cliquer sur un bouton pour vous connecter !</p>'; // Message
			} else { // Sinon, il n'est pas connecté
				$query = $connexion->prepare('UPDATE membres SET identifier = ? WHERE mail = ?'); // On modifie la table
				$req->execute(array($identifier, $email));
				$query = $connexion->query('SELECT id, pseudo FROM membres WHERE mail = \''.$email.'\''); // On récupère les données concernant le membre
				$donnees = $query->fetch(PDO::FETCH_ASSOC);
				$_SESSION['pseudo'] = $donnees['pseudo']; // On connecte le membre
				$_SESSION['id'] = $donnees['id'];
				$message = '<p>Le compte a bien été lié. Vous n\'avez qu\'à cliquer sur un bouton pour vous connecter !</p>'; // Message
			}
		}

	} else { /* Une erreur est survenue */
		// On affiche l'erreur
		echo 'Une erreur est survenue : ' . $auth_info['err']['msg'];
	}
}
echo $message;
?>

Voila, vous avez maintenant un module fonctionnel d'inscription et connexion en un clic ! Bonne route avec JanRain ! :)
Voici quelques liens utiles :

Ce tutoriel aura très bientôt une suite : nous verrons comment créer soi-même son système, en étant indépendant de Janrain. ;)

Exemple de certificat de réussite
Exemple de certificat de réussite