Italian (Italiano) translation by Francesco (you can also view the original English article)
In questo articolo, vedremo come si potrebbe impostare un vero e proprio server OAuth2 in Laravel utilizzando la libreria di Laravel Passport. Esamineremo le configurazioni di server necessarie insieme ad un esempio reale per dimostrare come si può usare OAuth2 API.
Presumo che hai familiarità con i concetti base di OAuth2 e il flow poichè stiamo andando a discuterli nel contesto di Laravel. Infatti, la libreria Passport di Laravel rende davvero facilissimo impostare un server Oauth2 nella tua applicazione. Così, altre applicazioni di terze parti possono consumare le APIs fornite dalla tua applicazione.
Nella prima metà dell'articolo installeremo e configureremo le librerie necessarie, mentre nella seconda metà vedremo come impostare delle risorse dimostrative nella tua applicazione e consumarle attraverso applicazioni di terze parti.
Configurazione del server
In questa sezione vedremo come installare le dipendenze che sono richieste dalla libreria Passport per funzionare con Laravel. Dopo l'installazione ci sarà bisogno di alcune configurazioni per far sì che Laravel possa riconoscere la libreria Passport.
Andiamo avanti ad installare la libreria di Passport utilizzando composer.
$composer require laravel/passport
E' tutto quello che occorre per quanto riguarda l'installazione della libreria Passport. Ora assicuriamoci che Laravel la riconosca.
Lavorando con Laravel, sei probabilmente a conoscenza del concetto di service provider che permette di configurare i servizi nella tua applicazione. Quando vuoi attivare un servizio nella tua applicazione Laravel, hai bisogno di aggiungere un campo del service provider nel file config.app.php
.
Se ancora non conosci i service providers di Laravel, ti consiglio vivamente di guardare questo articolo introduttivo che spiega le nozioni di base sui service provider in Laravel.
Nel nostro caso, abbiamo solo bisogno di aggiungere il provider PassportServiceProvider
all'elenco dei providers in config/app.php
come illustrato nel seguente frammento di codice.
... ... 'providers' => [ /* * Laravel Framework Service Providers... */ Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, Illuminate\Cookie\CookieServiceProvider::class, Illuminate\Database\DatabaseServiceProvider::class, Illuminate\Encryption\EncryptionServiceProvider::class, Illuminate\Filesystem\FilesystemServiceProvider::class, Illuminate\Foundation\Providers\FoundationServiceProvider::class, Illuminate\Hashing\HashServiceProvider::class, Illuminate\Mail\MailServiceProvider::class, Illuminate\Notifications\NotificationServiceProvider::class, Illuminate\Pagination\PaginationServiceProvider::class, Illuminate\Pipeline\PipelineServiceProvider::class, Illuminate\Queue\QueueServiceProvider::class, Illuminate\Redis\RedisServiceProvider::class, Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, Illuminate\Session\SessionServiceProvider::class, Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, /* * Package Service Providers... */ Laravel\Tinker\TinkerServiceProvider::class, /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, Laravel\Passport\PassportServiceProvider::class, ], ... ...
Successivamente, è necessario eseguire il comando migrate
di artisan, per creare le tabelle necessarie alla libreria Passport nel database.
$php artisan migrate
Per essere precisi, crea le seguenti tabelle nel database.
oauth_access_tokens oauth_auth_codes oauth_clients oauth_personal_access_clients oauth_refresh_tokens
Poi, abbiamo bisogno di generare una coppia di chiavi pubblica e privata che verrà utilizzato dalla libreria Passport per la crittografia. Come previsto, Passport fornisce un comando artisan per crearla facilmente.
$php artisan passport:install
Questo dovrebbe aver creato le chiavi in storage/oauth-public.key
e storage/oauth-private.key
. Crea anche le credenziali di alcuni client demo su cui torneremo più tardi.
Andando avanti, aggiungiamo oauth al modello utente esistente che Laravel utilizza per l'autenticazione. Per farlo, abbiamo bisogno di aggiungere il trai di HasApiTokens
alla classe del modello User
. Facciamolo come illustrato nel seguente frammento di codice.
<?php namespace App; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; use Laravel\Passport\HasApiTokens; class User extends Authenticatable { use HasApiTokens; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; }
Il trait HasApiToken
contiene dei metodi di supporto che vengono usati per validare i tokens nella richiesta e controllare che lo scope delle risorse siano nel contesto dell'utente autenticato.
Inoltre, abbiamo bisogno di registrare le routes fornite dalla libreria Passport nella nostra applicazione Laravel. Questi percorsi verranno utilizzati per le operazioni standard di OAuth2 come autorizzazione, richiesta di token di accesso e simili.
Nel metodo di boot del file app/Providers/AuthServiceProvider.php
, registriamo i percorsi di Passaporto.
... ... /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Passport::routes(); } ... ...
Ultimo ma non meno importante, abbiamo bisogno di cambiare il driver api
dal token al passaporto nel file config/auth.php
, poichè stiamo andando a utilizzare la libreria di Passport per l'autenticazione di API.
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
Finora, abbiamo fatto tutto quello che è richiesto, per quanto riguarda la configurazione del server OAuth2.
Configurare le risorse Demo
Nella sezione precedente, abbiamo fatto tutto il lavoro duro per impostare il server di autenticazione OAuth2 nella nostra applicazione. In questa sezione, imposteremo una risorsa di demo che può essere richiesta tramite la chiamata API.
Cerchiamo di mantenere le cose semplici. La nostra risorsa demo restituisce le informazioni dell'utente purché vi sia un parametro uid
valido presente nella richiesta GET
.
Creiamo un controller app/Http/Controllers/UserController.php
con il seguente contenuto.
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\User; class UserController extends Controller { public function get(Request $request) { $user_id = $request->get("uid", 0); $user = User::find($user_id); return $user; } }
Come al solito, è necessario aggiungere una route associata pure, che si suppone di aggiungere nel file routes/web.php
. Ma stiamo parlando del percorso delle API, e quindi necessita un trattamento speciale.
Le route di API sono definite nel file routes/api.php
. Così, andiamo avanti ad aggiungere il nostro percorso di API personalizzato come illustrato nel seguente frammento di codice.
<?php use Illuminate\Http\Request; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); // custom API route Route::middleware('auth:api')->get('/user/get', 'UserController@get');
Anche se lo abbiamo definito come /user/get
, la route API effettiva è /api/user/get
, che è quello che si dovrebbe usare quando si richiede una risorsa su tale route. Il prefisso di api
viene gestito automaticamente da Laravel, e non devi preoccuparti di questo!
Nella prossima e ultima sezione, discuteremo come si possono creare credenziali client e consumare l'API OAuth2.
Come utilizzare le API OAuth2
Ora che abbiamo creato il server OAuth2 nella nostra applicazione, qualsiasi utente terzo può collegarsi al nostro server con OAuth e consumare le API disponibili nella nostra applicazione.
Prima di tutto, applicazioni di terze parti devono registrarsi con la nostra applicazione al fine di essere in grado di utilizzare le API. In altre parole, essi sono considerati come applicazioni client, e riceveranno un id client e un secret client al momento della registrazione.
La libreria di Passport fornisce un comando di artisan per creare client account senza molta fatica. Andiamo avanti a creare un account del client di demo.
$php artisan passport:client Which user ID should the client be assigned to?: > 1 What should we name the client?: > Demo OAuth2 Client Account Where should we redirect the request after authorization? [https://localhost/auth/callback]: > http://localhost/oauth2_client/callback.php New client created successfully. Client ID: 1 Client secret: zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01
Quando si esegue il comando passaport::client
, vengono effettuate un paio di domande prima di creare l'account del client. Tra queste, ce ne è una importante che ti chiede l'URL di callback
.
L'URL di callback
è quello dove l'utente verrà rimandato indietro dopo l'autorizzazione di terze parti. E questo è dove verrà inviato il codice di autorizzazione che è supposto essere utilizzato per scambiare il token di accesso. Stiamo per creare tale file in un attimo.
Ora, siamo pronti a testare le API OAuth2 nell'applicazione Laravel.
A scopo dimostrativo, creeremo la directory oauth2_client
sotto la root in primo luogo. Idealmente, questi file dovranno essere situati all'estremità di terze parti che vuole consumare API nella nostra applicazione Laravel.
Creiamo il file oauth2_client/auth_redirection.php
con il seguente contenuto.
<?php $query = http_build_query(array( 'client_id' => '1', 'redirect_uri' => 'http://localhost/oauth2_client/callback.php', 'response_type' => 'code', 'scope' => '', )); header('Location: http://your-laravel-site-url/oauth/authorize?'.$query);
Assicurarsi di modificare i parametri client_id
e redirect_uri
per riflettere le proprie impostazioni — quelli che si sono utilizzate durante la creazione account del client di demo.
Quindi, creiamo il file oauth2_client/callback.php
con il seguente contenuto.
<?php // check if the response includes authorization_code if (isset($_REQUEST['code']) && $_REQUEST['code']) { $ch = curl_init(); $url = 'http://your-laravel-site-url/oauth/token'; $params = array( 'grant_type' => 'authorization_code', 'client_id' => '1', 'client_secret' => 'zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01', 'redirect_uri' => 'http://localhost/oauth2_client/callback.php', 'code' => $_REQUEST['code'] ); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $params_string = ''; if (is_array($params) && count($params)) { foreach($params as $key=>$value) { $params_string .= $key.'='.$value.'&'; } rtrim($params_string, '&'); curl_setopt($ch,CURLOPT_POST, count($params)); curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string); } $result = curl_exec($ch); curl_close($ch); $response = json_decode($result); // check if the response includes access_token if (isset($response->access_token) && $response->access_token) { // you would like to store the access_token in the session though... $access_token = $response->access_token; // use above token to make further api calls in this session or until the access token expires $ch = curl_init(); $url = 'http://your-laravel-site-url/api/user/get'; $header = array( 'Authorization: Bearer '. $access_token ); $query = http_build_query(array('uid' => '1')); curl_setopt($ch,CURLOPT_URL, $url . '?' . $query); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); $result = curl_exec($ch); curl_close($ch); $response = json_decode($result); var_dump($result); } else { // for some reason, the access_token was not available // debugging goes here } }
Ancora una volta, assicurarsi di regolare gli URL e le credenziali del client secondo la configurazione nel file di cui sopra.
Come funziona complessivamente
In questa sezione, proveremo complessivamente dal punto di vista di un utente finale. Come utente finale, ci sono due applicazioni di fronte a voi:
- La prima è l'applicazione Laravel su cui hai già un account. Contiene le informazioni che tu puoi condividere con altre applicazioni di terze parti.
- La seconda è l'applicazione client di terze parti demo,
auth_redirection.php
ecallback.php
, che vuole recuperare le informazioni dall'applicazione Laravel utilizzando l'API di OAuth.
Il flusso inizia dall'applicazione client di terze parti. Andiamo avanti e apriamo l'URL http://localhost/oauth2_client/auth_redirection.php nel browser, che dovrebbe reindirizzare l'utente all'applicazione Laravel. Se non hai già effettuato il login nell'applicazione Laravel, l'applicazione vi chiederà di farlo in primo luogo.
Una volta che l'utente è connesso, l'applicazione visualizza la pagina di autorizzazione.
Se l'utente autorizza tale richiesta, l'utente verrà reindirizzato all'applicazione client di terze parti a http://localhost/oauth2_client/callback.php insieme al parametro code
come parametro GET
che contiene il codice di autorizzazione.
Una volta che l'applicazione di terze parti riceve il codice di autorizzazione, potrebbe scambiare quel codice con l'applicazione di Laravel per ottenere il token di accesso. E questo è esattamente ciò che viene fatto nel codice del file oauth2_client/callback.php
.
$ch = curl_init(); $url = 'http://your-laravel-site-url/oauth/token'; $params = array( 'grant_type' => 'authorization_code', 'client_id' => '1', 'client_secret' => 'zMm0tQ9Cp7LbjK3QTgPy1pssoT1X0u7sg0YWUW01', 'redirect_uri' => 'http://localhost/oauth2_client/callback.php', 'code' => $_REQUEST['code'] ); curl_setopt($ch,CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $params_string = ''; if (is_array($params) && count($params)) { foreach($params as $key=>$value) { $params_string .= $key.'='.$value.'&'; } rtrim($params_string, '&'); curl_setopt($ch,CURLOPT_POST, count($params)); curl_setopt($ch,CURLOPT_POSTFIELDS, $params_string); } $result = curl_exec($ch); curl_close($ch); $response = json_decode($result);
Successivamente, l'applicazione di terze parti controlla la risposta della richiesta CURL per vedere se contiene un token di accesso valido in primo luogo.
Non appena l'applicazione di terze parti ottiene il token di accesso, potrebbe utilizzare tale token per effettuare ulteriori chiamate API per richiedere risorse dall'applicazione Laravel. Naturalmente, il token di accesso deve essere passato in ogni richiesta che richiede risorse dall'applicazione Laravel.
Abbiamo cercato di imitare il caso di utilizzo in quanto l'applicazione di terze parti vuole accedere le informazioni dell'utente dall'applicazione Laravel. E abbiamo già costruito un endpoint API, http://your-laravel-site-url/api/user/get, nell'applicazione Laravel che facilita il compito.
// check if the response includes access_token if (isset($response->access_token) && $response->access_token) { // you would like to store the access_token in the session though... $access_token = $response->access_token; // use above token to make further api calls in this session or until the access token expires $ch = curl_init(); $url = 'http://your-laravel-site-url/api/user/get'; $header = array( 'Authorization: Bearer '. $access_token ); $query = http_build_query(array('uid' => '1')); curl_setopt($ch,CURLOPT_URL, $url . '?' . $query); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); $result = curl_exec($ch); curl_close($ch); $response = json_decode($result); var_dump($result); }
Questo è il flusso completo per consumare le API OAuth2 in Laravel.
E con questo, abbiamo raggiunto la fine di questo articolo.
Conclusione
Oggi, abbiamo esplorato la libreria Passport in Laravel, che permette di impostare un server di OAuth2 in un'applicazione molto facilmente.
Per quelli di voi che hanno iniziato con Laravel o stanno cercando approfondimenti, siti completi o applicazioni con estensioni, abbiamo una varietà di cose su cui si può studiare nel market di Envato.
Non esitate a condividere i vostri pensieri e le domande utilizzando il feed qui sotto!