環境
- PHP7.2
- Laravel5.5
作るもの
- /api/login ユーザーとパスワードを送るとトークンが発行される。
- /api/me ユーザーの情報を返す。トークンが無いとアクセスできない。
認証機能を導入
まずはLaravelに備わっている認証機能を有効にしておきます。
php artisan make:auth
php artisan migrate
これだけでログイン機能ができる。
WebAPIのときに使うのでユーザーを登録しておきましょう。
composerでjwt-authをインストール
jwt-authをLaravelプロジェクトにインストールします。
composer require tymon/jwt-auth 1.0.0-rc2
Laravel5.5>= には1.0以上のjwt-authが必要なのでバージョンを指定します。
次にjwt-authの初期設定を行います。
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
config/jwt.php
が生成されます。
最後に秘密鍵を生成。
php artisan jwt:secret
Userモデルを修正
Userモデルをjwt-authに対応させるため、編集します。
<?php
namespace App;
+use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
-class User extends Authenticatable
+class User extends Authenticatable implements JWTSubject
{
...
+ public function getJWTIdentifier()
+ {
+ return $this->getKey();
+ }
+ public function getJWTCustomClaims()
+ {
+ return [];
+ }
}
guardを修正
guardは認証を管理する仕組みで、デフォルトではweb
とapi
があります。
web
は普通にhtmlからのログインを管理しています。
一方api
は名前の通り、WebAPIのログインです。
jwt-auth
を使うのでapi
をjwt
に変えます。
config/auth.php
を編集
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
- 'driver' => 'token',
+ 'driver' => 'jwt',
'provider' => 'users',
],
],
ApiControllerを生成
次にAPIのコントローラーを作成します。
php artisan make:controller ApiController
app/Http/Controllers/ApiController.php
が生成されます。
以下のように変更しましょう。
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
class ApiController extends Controller
{
function login() {
$credentials = request(['email', 'password']);
if (! $token = auth("api")->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function me()
{
return response()->json(auth()->user());
}
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth("api")->factory()->getTTL() * 60
]);
}
}
ログインとユーザー情報を取得するメソッドを作成しました。
routes/api.phpを編集
routesファイルを編集。
<?php
use Illuminate\Http\Request;
Route::group(["middleware" => "guest:api"], function () {
Route::post("/login", "ApiController@login");
});
Route::group(["middleware" => "auth:api"], function () {
Route::get("/me", "ApiController@me");
});
/login
はguest
を指定して認証がなくてもアクセスできるように、/me
はログインしてトークンを送らないとアクセスできないようにしました。
試す
curl
で試してみます。
email
とpassword
は上のユーザーを登録したときのを指定します。
curl http://<laravel-host>/api/login -d email=hoge@example.com -d password=hoge12345
すると以下のようにトークンを含んだjsonが返ってきます。
{"access_token":"eyJ0eXAiOiJKV2QiLC2hbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9sYXJhdmVsLXRha2FzYW45ODkuYzl1c2Vygy5pb1wvYXBpXC9sb2dpbiIsImlhdCI6MTUyMjE1NTY1OSwiZXhwIjoxNTIyMTU5MjU5xCJuYmYiOjE1MxIxNTU2NTksImp0aSI6Inh6MHRsQ1hHNmgwQ1g3V0UiLCJzdWIiOjEsInBydiI6Ijg3bTBhZjFlZjlmZDE1ODEyZmorYzk3MTUzYTE0ZTBJfDQ3NTQ2YWEifQ.BdoHaKFy8XLOSaTKBOhA1D3i5NPUGzG9E1lsBQefEhs","token_type":"bearer","expires_in":3600}
そしてトークンを使って認証が必要なurlにアクセスしてみます。
Authorization
ヘッダーにBearer: <token>
を付けて送信します。
curl -H "Authorization: Bearer eyJ0eXAi...." http://<laravel-host>/api/me
実行すると
{"id":1,"name":"hoge","email":"hoge@example.com","created_at":"2018-03-26 14:33:21","updated_at":"2018-03-26 14:33:21"}
ログインしているユーザーの情報が返ってきました。
これを応用すればユーザー認証ができるWebAPIが作れます。