German (Deutsch) translation by Wei Zhang (you can also view the original English article)
In diesem Artikel werden wir den Auth0-Dienst untersuchen, der Authentifizierung und Autorisierung als Dienst bereitstellt. Mit Auth0 können Sie grundlegende Authentifizierungs- und Autorisierungsfunktionen für Ihre Apps im Handumdrehen einrichten.
Was ist Auth0?
Auth0 ist eine Authentifizierung als Service-Tool, das die Implementierung von authentifizierungsbezogenen Funktionen auf Ihrer Website zu einem Kinderspiel macht. Wenn Sie eine App entwickelt haben und nur die Authentifizierungs- und Autorisierungsfunktionen auslagern möchten, sollten Sie einen Dienst wie Auth0 in Erwägung ziehen.
Lassen Sie mich kurz zusammenfassen, was Auth0 zu bieten hat:
- Einmalige Anmeldung
- Multifaktor-Authentifizierung
- Passwortlose Logins
- Benutzerverwaltung
- und vieles mehr
In diesem Artikel werden einige Single Sign-On-Methoden erläutert, die Sie in Ihren Webanwendungen implementieren können, um die vom Auth0-Dienst bereitgestellten Authentifizierungsfunktionen zu nutzen.
In der ersten Hälfte des Artikels erfahren Sie, wie Sie grundlegende Authentifizierungsfunktionen in einer serverseitigen PHP-Webanwendung einrichten. In der zweiten Hälfte erkläre ich, wie Sie Ihre benutzerdefinierten APIs sichern können, indem Sie die OAuth-Autorisierung mit dem Auth0-Dienst einrichten.
Serverseitige Authentifizierung Integration
In diesem Abschnitt erfahren Sie, wie Sie mithilfe von Auth0 schnell die Basisauthentifizierung für serverseitige Webanwendungen einrichten können. Tatsächlich bietet das Auth0-Team bereits ein praktisches GitHub-Beispiel, das grundlegende Beispiele demonstriert, also werden wir das verwenden, anstatt das Rad neu zu erfinden.
Bevor Sie fortfahren, stellen Sie sicher, dass Sie Composer installieren, damit die eigentlichen Auth0 SDKs mit der Datei composer.json
installiert werden. Wenn Sie den Beispielen in diesem Artikel folgen möchten, können Sie auch einen kostenlosen Account mit Auth0 erwerben.
Richten Sie das Projekt ein
Lassen Sie uns weitermachen und den Klon des Samples-Projekts greifen.
git clone https://github.com/auth0-samples/auth0-php-web-app.git .
Fahren Sie mit dem Befehl composer install
fort, um die Abhängigkeiten zu installieren.
cd 00-Starter-Seed composer install
Laut der Datei composer.json sollten die Pakete vlucas/phpdotenv
und auth0/auth0-php
installiert sein.
{ "name": "auth0/basic-webapp-sample", "description": "Basic sample for securing a WebApp with Auth0", "require": { "vlucas/phpdotenv": "2.4.0", "auth0/auth0-php": "~5.0" }, "license": "MIT", "authors": [ { "name": "Martin Gontovnikas", "email": "martin@gon.to" }, { "name": "Germán Lena", "email": "german.lena@gmail.com" } ] }
Die Bibliothek vlucas/phpdoten
v wird zum Initialisieren von Umgebungsvariablen aus der .env-Datei verwendet. Auf diese Weise können Sie die Konfiguration von dem Code trennen, der zwischen den Umgebungen wechselt.
Auf der anderen Seite ist das auth0/auth0-php
Paket dasjenige, das uns helfen wird, die Autorisierung in unserer Anwendung einzurichten.
Als Nächstes richten wir die Konfiguration für unsere Anwendung in der .env-Datei ein. Gehen Sie voran und erstellen Sie die .env-Datei, indem Sie sie aus der .env.example-Datei kopieren.
cp .env.example .env
Es enthält Konfigurationswerte, die von der Auth0-Bibliothek verwendet werden.
AUTH0_CLIENT_ID={CLIENT_ID} AUTH0_DOMAIN={DOMAIN_NAME} AUTH0_CLIENT_SECRET={CLIENT_SECRET} AUTH0_CALLBACK_URL={CALLBACK_URL} AUTH0_AUDIENCE=
Sie sollten die meisten Einstellungen unter Applications > Default App > Settings im Auth0-Dashboard finden können. Bitte beachten Sie, dass ich die Standardanwendung verwende, die vom System erstellt wurde. Natürlich können Sie eine neue Anwendung erstellen, wenn Sie dies möchten.
Die AUTH0_CALLBACK_URL
ist die URL Ihrer Anwendung, bei der Auth0 Benutzer nach dem Anmelden und Abmelden umleiten wird. Der Wert, den Sie in diesem Feld festlegen, muss unter den Allowed Callback URLs
unter den Anwendungseinstellungen auf dem Auth0-Dashboard konfiguriert werden.
Sie finden drei Hauptdateien, die den Großteil der Authentifizierungslogik implementieren.
- index.php: Dies ist die Hauptseite, die basierend auf dem Status des Benutzers entweder eine Schaltfläche zum Anmelden oder Abmelden anzeigt.
- login.php: Dieses Skript wird gestartet, wenn Sie auf den Login-Button klicken und Benutzer zur Anmelde-Schnittstelle Auth0 umleiten. Nach der Anmeldung werden sie zurück zur
AUTH0_CALLBACK_URL
weitergeleitet. - logout.php: Dieses Skript wird gestartet, wenn du auf den Logout-Button klickst und Benutzer zu Auth0 im Hintergrund weiterleitet, sie ausloggst und sie zurück zur
AUTH0_CALLBACK_URL
bringt.
Wichtige Projektdateien
Lassen Sie uns schnell jede Datei im Starter-Projekt durchgehen.
Das Anmeldeskript
Wir beginnen mit der login.php Datei.
<?php require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/dotenv-loader.php'; use Auth0\SDK\Auth0; $domain = getenv('AUTH0_DOMAIN'); $client_id = getenv('AUTH0_CLIENT_ID'); $client_secret = getenv('AUTH0_CLIENT_SECRET'); $redirect_uri = getenv('AUTH0_CALLBACK_URL'); $audience = getenv('AUTH0_AUDIENCE'); if($audience == ''){ $audience = 'https://' . $domain . '/userinfo'; } $auth0 = new Auth0([ 'domain' => $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_access_token' => true, 'persist_refresh_token' => true, ]); $auth0->login();
Zu Beginn haben wir Autoloader integriert, die für das Laden von Klassen mit Aut0- und Umgebungsvariablen zuständig sind. Anschließend initialisieren wir Konfigurationsvariablen aus der .env-Datei mit der Funktion getenv
.
Als nächstes instanziieren wir das Auth0-Objekt und rufen die Login-Methode auf, die Benutzer zur Anmeldung an Auth0 weiterleitet. Nach der Anmeldung werden die Nutzer auf unsere Website weitergeleitet.
Sie können sich mit Ihren sozialen Accounts wie Facebook, Google und Ähnlichem anmelden oder ein neues Konto bei der Anmeldung erstellen. In beiden Fällen erstellt Auth0 Datensätze für die neuen Benutzer an ihrem Ende. Unter Connections> Social können Sie auf dem Auth0-Dashboard verschiedene soziale Logins aktivieren. Sie können auch die Liste der Benutzer überprüfen, die mit Auth0 im Auth0-Dashboard unter dem Link Users angemeldet sind.
Das Logout-Skript
Als nächstes schauen wir uns die logout.php Datei an.
<?php require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/dotenv-loader.php'; use Auth0\SDK\Auth0; $domain = getenv('AUTH0_DOMAIN'); $client_id = getenv('AUTH0_CLIENT_ID'); $client_secret = getenv('AUTH0_CLIENT_SECRET'); $redirect_uri = getenv('AUTH0_CALLBACK_URL'); $audience = getenv('AUTH0_AUDIENCE'); if($audience == ''){ $audience = 'https://' . $domain . '/userinfo'; } $auth0 = new Auth0([ 'domain' => $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_refresh_token' => true, ]); $auth0->logout(); $return_to = 'https://' . $_SERVER['HTTP_HOST']; $logout_url = sprintf('http://%s/v2/logout?client_id=%s&returnTo=%s', $domain, $client_id, $return_to); header('Location: ' . $logout_url); die();
Dies funktioniert genauso wie die login.php-Datei, außer dass sie beim Abmelden aufgerufen wird. Die Methode logout
wird aufgerufen, um eine Benutzersitzung in Ihrer App abzubrechen. Anschließend wird der Benutzer zu Auth0 weitergeleitet, damit der Dienst über die Abmeldeaktivität des Benutzers informiert wird. Abschließend wird der Benutzer zurück zu Ihrer Anwendung geleitet.
Die Indexdatei
Schließlich gehen wir die Datei index.php durch, die der Einstiegspunkt unserer Anwendung ist.
<?php // Require composer autoloader require __DIR__ . '/vendor/autoload.php'; require __DIR__ . '/dotenv-loader.php'; use Auth0\SDK\Auth0; $domain = getenv('AUTH0_DOMAIN'); $client_id = getenv('AUTH0_CLIENT_ID'); $client_secret = getenv('AUTH0_CLIENT_SECRET'); $redirect_uri = getenv('AUTH0_CALLBACK_URL'); $audience = getenv('AUTH0_AUDIENCE'); if($audience == ''){ $audience = 'https://' . $domain . '/userinfo'; } $auth0 = new Auth0([ 'domain' => $domain, 'client_id' => $client_id, 'client_secret' => $client_secret, 'redirect_uri' => $redirect_uri, 'audience' => $audience, 'scope' => 'openid profile', 'persist_id_token' => true, 'persist_access_token' => true, 'persist_refresh_token' => true, ]); $userInfo = $auth0->getUser(); ?> <html> <head> <script src="http://code.jquery.com/jquery-3.1.0.min.js" type="text/javascript"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- font awesome from BootstrapCDN --> <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet"> <link href="public/app.css" rel="stylesheet"> </head> <body class="home"> <div class="container"> <div class="login-page clearfix"> <?php if(!$userInfo): ?> <div class="login-box auth0-box before"> <img src="https://i.cloudup.com/StzWWrY34s.png" /> <h3>Auth0 Example</h3> <p>Zero friction identity infrastructure, built for developers</p> <a class="btn btn-primary btn-lg btn-login btn-block" href="login.php">Sign In</a> </div> <?php else: ?> <div class="logged-in-box auth0-box logged-in"> <h1 id="logo"><img src="//cdn.auth0.com/samples/auth0_logo_final_blue_RGB.png" /></h1> <img class="avatar" src="<?php echo $userInfo['picture'] ?>"/> <h2>Welcome <span class="nickname"><?php echo $userInfo['nickname'] ?></span></h2> <a class="btn btn-warning btn-logout" href="/logout.php">Logout</a> </div> <?php endif ?> </div> </div> </body> </html>
Hier haben wir die getUser
-Methode des $auth0
-Objekts verwendet, um zu sehen, ob es eine aktive Sitzung gibt. Wenn es keine aktive Sitzung gibt, zeigen wir den Sign In-Link an, der einen Benutzer zur login.php führt und den Login-Flow initiiert. Auf der anderen Seite werden wir den Benutzer begrüßen und den Logout-Link anzeigen, wenn der Benutzer bereits angemeldet ist.
Das war die Implementierung eines grundlegenden Authentifizierungsablaufs für serverseitige Apps.
Sichern Sie Ihre benutzerdefinierten APIs mit OAuth2
In diesem Abschnitt erfahren Sie, wie Sie Ihre benutzerdefinierten APIs sichern können, indem Sie den OAuth2-Berechtigungscode-Genehmigungsablauf implementieren. Ich hoffe, Sie kennen den Standardfluss des Autorisierungscode-Grants, da wir hier nicht näher darauf eingehen werden. Hier findest du einige unserer Beiträge auf Envato Tuts +, wenn du mit OAuth2 auf dem Laufenden sein willst.
OAuth 2.0 - Das Gute, das Schlechte & Das Hässliche
So authentifizieren Sie Benutzer mit Twitter OAuth 2.0
Stattdessen tauchen wir gleich in die eigentliche Implementierung ein. Gehen Sie voran und erstellen Sie eine auth_code_grant_example.php Datei mit den folgenden Inhalten.
<?php session_start(); if (!isset($_GET['code'])) { // Check if we need to show the "Sign In" link $params = array ( 'audience' => '{AUDIENCE}', 'scope' => 'profile', 'response_type' => 'code', 'client_id' => '{CLIENT_ID}', 'state' => 'SomeRandomString', 'redirect_uri' => '{CALLBACK_URL}' ); $_SESSION['oauth2state']=$params['state']; $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } ?> <a href="https://{AUTH0_DOMAIN}/authorize?<?php echo $str_params;?>"> Sign In </a> <?php } elseif (empty($_GET['state']) || (isset($_SESSION['oauth2state']) && $_GET['state'] !== $_SESSION['oauth2state'])) { // If the "state" var is present in the $_GET, let's validate it if (isset($_SESSION['oauth2state'])) { unset($_SESSION['oauth2state']); } exit('Invalid state'); } elseif(isset($_GET['code']) && !empty($_GET['code'])) { // If the auth "code" is present in the $_GET // let's exchange it for the access token $params = array ( 'grant_type' => 'authorization_code', 'client_id' => '{CLIENT_ID}', 'client_secret' => '{CLIENT_SECRET}', 'code' => $_GET['code'], 'redirect_uri' => '{CALLBACK_URL}' ); $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://{AUTH0_DOMAIN}/oauth/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $str_params )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response:" . $curl_error; } else { $arr_json_data = json_decode($curl_response); if (isset($arr_json_data->access_token)) { $access_token = $arr_json_data->access_token; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://{YOUR_API_DOMAIN}/demo_api_server.php", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "Authorization: Bearer {$access_token}" ) )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response from DEMO API:" . $curl_error; } else { echo "Demo API Response:" . $curl_response; } } else { echo 'Invalid response, no access token was found.'; } } }
Schauen wir uns an, wie dieser Code funktioniert!
Beginn des Autorisierungsablaufs
Zuerst bereiteten wir einen Link vor, der den Benutzer an den Auth0-Server sendet, um den Autorisierungsablauf zu beginnen.
// Check if we need to show the "Sign In" link $params = array ( 'audience' => '{AUDIENCE}', 'scope' => 'profile', 'response_type' => 'code', 'client_id' => '{CLIENT_ID}', 'state' => '{SOME_RANDOM_STRING}', 'redirect_uri' => '{CALLBACK_URL}' ); $_SESSION['oauth2state']=$params['state']; $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } ?> <a href="https://{AUTH0_DOMAIN}/authorize?<?php echo $str_params;?>"> Sign In </a>
Ersetzen Sie {AUDIENCE}
, {CLIENT_ID}
und {CALLBACK_URL}
durch Werte, die Ihrer Anwendung entsprechen. Der Parameter {AUDIENCE}
sollte durch den Wert des Felds Identifier unter APIs> {YOUR API APPLICATION}> Settings im Auth0-Dashboard ersetzt werden.
Der {SOME_RANDOM_STRING} sollte durch einen eindeutigen Wert ersetzt werden, der schwer zu erraten ist. Diese Zeichenfolge wird verwendet, um CSRF-Angriffe zu verhindern. Stellen Sie außerdem sicher, dass {AUTH0_DOMAIN}
durch Ihren Domänennamen ersetzt wird, wie bereits erwähnt.
Erhalten des Zugriffstokens
Wenn ein Nutzer auf den Sign In-Link klickt, wird er zur Authentifizierung an den Auth0-Server weitergeleitet. Nach der Authentifizierung werden Sie aufgefordert, den Zugriff der Anwendung auf Ihr Profil zu autorisieren. Nach der Autorisierung wird der Benutzer mit dem code
als $_GET
-Parameter zurück an Ihre Anwendung weitergeleitet.
Als nächstes können wir diesen code
austauschen, um das Zugriffstoken zu erhalten.
// If the auth "code" is present in the $_GET // let's exchange it for the access token $params = array ( 'grant_type' => 'authorization_code', 'client_id' => '{CLIENT_ID}', 'client_secret' => '{CLIENT_SECRET}', 'code' => $_GET['code'], 'redirect_uri' => '{CALLBACK_URL}' ); $str_params = ''; foreach($params as $key=>$value) { $str_params .= $key . "=" . urlencode($value) . "&"; } $curl = curl_init(); $curl_response = curl_exec($curl); curl_setopt_array($curl, array( CURLOPT_URL => "https://{AUTH0_DOMAIN}/oauth/token", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "POST", CURLOPT_POSTFIELDS => $str_params ));
Wie Sie sehen, benötigt ein einzelner CURL-Aufruf das Zugriffstoken.
Rufen Sie Ihren benutzerdefinierten API-Endpunkt auf
Sobald Sie über das Zugriffstoken verfügen, können Sie Ihren benutzerdefinierten API-Endpunkt aufrufen, indem Sie ihn in die Kopfzeile aufnehmen.
$access_token = $arr_json_data->access_token; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "http://{YOUR_API_DOMAIN}/demo_api_server.php", CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => "GET", CURLOPT_HTTPHEADER => array( "Authorization: Bearer {$access_token}" ) )); $curl_response = curl_exec($curl); $curl_error = curl_error($curl); curl_close($curl); if ($curl_error) { echo "Error in the CURL response from DEMO API:" . $curl_error; } else { echo "Demo API Response:" . $curl_response; }
Ein Auth0-geschützter API-Endpunkt
Die fiktive API-Ressourcendatei demo_api_server.php könnte etwa so aussehen:
<?php // Require composer autoloader require __DIR__ . '/vendor/autoload.php'; use Auth0\SDK\JWTVerifier; try { $verifier = new JWTVerifier([ 'supported_algs' => ['{HASHING_ALGORITHM}'], 'valid_audiences' => ['{AUDIENCE}'], 'authorized_iss' => ['{DOMAIN}'] ]); $access_token = getBearerToken(); $token_info = $verifier->verifyAndDecode($access_token); echo json_encode(array('date'=>'API Resource Data!!')); } catch(\Auth0\SDK\Exception\CoreException $e) { throw $e; echo json_encode(array('error'=>$e->getMessage())); } function getAuthorizationHeader() { $headers = null; if (isset($_SERVER['Authorization'])) { $headers = trim($_SERVER["Authorization"]); } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI $headers = trim($_SERVER["HTTP_AUTHORIZATION"]); } elseif (function_exists('apache_request_headers')) { $requestHeaders = apache_request_headers(); // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); //print_r($requestHeaders); if (isset($requestHeaders['Authorization'])) { $headers = trim($requestHeaders['Authorization']); } } return $headers; } function getBearerToken() { $headers = getAuthorizationHeader(); // HEADER: Get the access token from the header if (!empty($headers)) { if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { return $matches[1]; } } return null; }
Lasst uns schnell die wichtigen Teile dieses Codes durchgehen.
Validieren des Zugriffstokens
Es liegt in Ihrer Verantwortung, das eingehende Zugriffstoken zu überprüfen, bevor Sie der geschützten Ressource Zugriff gewähren. Und genau das haben wir im folgenden Ausschnitt gemacht. Wir haben die JWTVerifier
-Dienstprogrammklasse verwendet, um das Zugriffstoken zu validieren.
try { $verifier = new JWTVerifier([ 'supported_algs' => ['{SIGNING_ALGORITHM}'], 'valid_audiences' => ['{AUDIENCE}'], 'authorized_iss' => ['{DOMAIN}'] ]); $access_token = getBearerToken(); $token_info = $verifier->verifyAndDecode($access_token); echo json_encode(array('date'=>'API Resource Data!!')); } catch(\Auth0\SDK\Exception\CoreException $e) { throw $e; echo json_encode(array('error'=>$e->getMessage())); }
Der {SIGNING_ALGORITHM}
sollte durch den Wert des Signing Algorithm-Felds unter APIs> {YOUR API APPLICATION}> Settings ersetzt werden.
So können Sie Ihre benutzerdefinierten APIs schützen, wenn Sie den OAuth2-Flow im Auth0-Service verwenden möchten.
Fazit
Heute haben wir den Auth0-Dienst durchlaufen, der Authentifizierung und Autorisierung als Dienst bereitstellt. Nach der Einführung des Auth0-Dienstes haben wir anhand einiger praktischer Beispiele gezeigt, wie Sie es in Ihre PHP-Anwendungen integrieren können.
Bitte zögern Sie nicht, Ihre Vorschläge und Fragen mit dem unten stehenden Feed zu posten!
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weekly