Social Media Authentifizierung in Laravel 4 mit HybridAuth

07. April 2013 Web-Entwicklung von Eric Kubenka

Wer kennt es nicht? Man möchte nur mal schnell einen Kommentar auf einem Blog hinterlassen und wird beim Absenden darauf hingewiesen, dass doch ein Login oder eine Registration nötig sei. Für viele nervig, da neue Benutzerdaten irgendwo im Kopf gespeichert werden müssen. Abhilfe schafft hier die aufstrebende Social Media Authentifizierung: Die Möglichkeit sich auf Seiten mit Hilfe Eures Twitter-, Facebook- oder Google+-Kontos anzumelden. Doch wie funktioniert das Ganze? Und wie einfach ist es? Geht das auch mit Laravel?

 

Social Media Authentifizierung – Wie geht das?

Mittlerweile sind Euch auf einigen Webseiten bestimmt schon Schaltflächen wie “Sign in with Twitter” oder “Connect with Facebook” aufgefallen und ihr habt es bestimmt schon mal ausprobiert. Das Prinzip ist einfach. Statt einer aufwendigen Registration muss man als Nutzer lediglich die Freigaben für die jeweilige Anwendung setzen und schon kann man auch die internen Funktionen nutzen, ohne sich erneut irgendwelche Logindaten merken zu müssen.

Bei dieser Art der Authentifizierung setzen viele Anbieter, wie Facebook und Twitter auf die Kommunikation mittels des OAuth-Protokolls. Das Vorgehen basiert dabei meistens auf der “Two-Legged”-Methode. Dabei besitzt die Webseite, welche Eure Benutzerdaten der jeweiligen Social Network Site verwenden möchte, einen “Key”, sowie ein “Secret”, welche an die Social Media Site gesendet werden. Dort wird geprüft, ob die gesendeten Daten valide sind. Ist dies der Fall wird ein Token generiert und zurück zur Ursprungswebseite geschickt. Das Token und der mitgelieferte Verifikationsschlüssel wird nun erneut an beispielsweise Twitter gesendet und verarbeitet. Nach dem der Benutzer die Anfrage auf Nutzung der Daten beantwortet hat, wird das Ergebnis an die Webseite übermittelt. Entweder liegen nun die Nutzerdaten vor oder aber die Anfrage wurde abgelehnt. Damit ist der Prozess abgeschlossen. Wie mit den empfangenen Daten weiter verfahren wird ist von Seite zu Seite unterschiedlich.

 

Geht das auch mit laravel?

Klar, jedoch muss man die jeweiligen Requests selber schreiben oder man greift auf bestehende Bibliotheken zurück. Ich für meinen Fall empfehle die Bibliothek HybridAuth, welche alle wichtigen Methoden zum Anmelden, Abfragen, Abmelden und Verwalten der Schnittstellen bereits besitzt.

Laravel 4 setzt auf Composer, weshalb sich HybridAuth einfach einbinden lässt. Dazu muss die composer.json Datei wie folgt angepasst werden.

"require": {
	"laravel/framework": "4.0.*",
	"hybridauth/hybridauth": "*"
},

Danach sollten mittels folgender Kommandobefehlszeile die Projektabhängigkeiten aktualisiert werden.

composer update

Anschließend habe ich für Facebook und Twitter jeweils eine Entwickler-App angelegt, mit welcher ich die benötigten Keys und Secrets für die Erstellung der Tokens erhalte. HybridAuth setzt auf eine Konfigurationsdatei, welche im Verzeichnis “/app/config” unter dem Namen “hybridauth.php” abgelegt wird. Die zu definierende Basis-URL entspricht der URL, welche für die Callbacks seitens HybridAuth verwendet wird.

return array(
	"base_url" => URL::to('/social/authenticate/auth'),
	"providers" => array(
		"twitter" => array(
			"enabled" => true,
			"keys" => array(
				"key" => "mykey",
				"secret" => "9mysecret"
				)
		),
		"facebook" => array(
			"enabled" => true,
			"keys" => array(
				"id" => "myid",
				"secret" => "mysecret"
				)
		)
	),
);

Anschließend habe ich folgende Routen definiert. Dank des dynamischen Routings in Laravel sind so alle Anbieter abgedeckt, insofern man für das Generieren der URLs auch die gleichen Bezeichnungen wie für die verschiedenen Provider innerhalb der Config-Datei verwendet.

/**
 * GET-Route --> Home-Route
 */
Route::get('', array('as' => 'showWelcome', function(){
	return "Hello ;)";
}));

/**
 * GET-Route: Catch the provider for auth with other network and redirect to authenticate route
 */
Route::get('social/{provider}', array('as' => 'socialAuth', function($provider)
		{
				return Redirect::route('hybridauth', 'start')->with('provider', $provider);
		}));

/**
 * GET-Route: Catch action and process the login via hybrid Auth
 */
Route::get('social/authenticate/{action}', array("as" => "hybridauth", function($action = "")
		{
				if (Session::has('provider'))
				{
						$provider = Session::get('provider');
				}

				// if "auth" is set as "action" do login
				if ($action == "auth")
				{
						// process auth
						try
						{
								Hybrid_Endpoint::process();
						}
						catch (Exception $e)
						{
								// redirect home on error
								return Redirect::route('showWelcome')
																->with('hybridAuthError', 'Social Network Authentication failed');
						}

						return;
				}

				// if != auth create new HybridAuth-Object
				try
				{
						// create a new HybridAuth Object by using the configuration file for secrets and token
						$socialAuth = new Hybrid_Auth(__DIR__ . '/config/hybridauth.php');
						// authenticate with Twitter
						$provider = $socialAuth->authenticate($provider);
						// fetch user profile
						$userProfile = $provider->getUserProfile();
				}
				catch (Exception $e)
				{
						// Redirect Home on error
						return Redirect::route('showWelcome')
														->with('hybridAuthError', 'Social Network Authentication failed');
				}

				// Store received data in session
				Session::put('hybridAuth', $userProfile);

				// logout
				$provider->logout();
				
				return Redirect::route('showWelcome')
								->with('hybridAuthSuccess', 'Social network Authentication successfull');
		}));

Die Links zum Auslösen der Aktionen habe ich dementsprechend wie folgt aufgebaut.

<a href="{'{ URl::route('socialAuth', 'twitter') }'}" class="btn">Sign in with Twitter</a>
<a href="{'{ URL::route('socialAuth', 'facebook') }'}" class="btn">Sign in with Facebook</a>

Damit ist eigentlich alles erledigt. Natürlich bietet es sich nun an, die UserId und den Provider in der Datenbank abzulegen. Anschließend kann bei folgenden Logins über den gleichen Dienst problemlos der Nutzer anhand der Id ermittelt werden. Um ihm dann “Mitgliederrechte” zu geben, bietet es sich an, die Laravel-Methode “Auth::attempt()” anzuwenden. Somit wird der Nutzer auch in der eigenen Laravel-Anwendung als angemeldeter Benutzer behandelt.

Natürlich stehen neben Facebook und Twitter noch weitere Social Networks zur Verfügung. Welche Provider von HybridAuth unterstützt werden, kann hier eingesehen werden.

Zurück