jwt:ログイン

2019-05-04

トークンベース認証システムであるjwt(Json Web Token)を使ってログイン手続きを実装して見ましょう。

概要

jwt認証システムを使ってログイン機能を実装してみようかと思います。このブログはシリーズで構成されています。jwt実装のためミドルウェア(Middleware)インストールや会員登録機能の実装に関しては以前のブログを確認してください。

リポジトリ(Repository)

私たちはjwt認証システムを実装したリポジトリ(Repository)を作りました。下記のリンクを押してリポジトリ(Repository)を確認してみてください。

開発環境構成

ここで説明する内容はLaradockとアンシブル(Ansible)を使って作ったララベル(Laravel)開発環境上で開発やテストします。Laradockとアンシブル(Ansible)を使ってララベル(Laravel)開発環境については下のブログを参考してください。

モデル修正

jwt認証システムの認証に使わられるモデル(Model)を下記のように修正します。

<?php
...
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
...
class User extends Authenticatable implements JWTSubject
{
    ...
    public function getJWTIdentifier() {
        return $this->getKey();
    }

    public function getJWTCustomClaims() {
        return [];
    }
}

ララベル(Laravel)の認証機能を使うためにモデル(Model)をAuthenticatableから継承しました。 また、jwtミドルウェア(Middleware)のインタフェースをJWTSubjectを通じて実装します。

public function getJWTIdentifier() {
    return $this->getKey();
}

public function getJWTCustomClaims() {
    return [];
}

上の関数はjwtミドルウェア(Middleware)のインタフェースを実装した部分です。

public function getJWTIdentifier() {
    return $this->getKey();
}

この部分はjwtのトークンを取得するための関数です。

public function getJWTCustomClaims() {
    return [];
}

この関数を説明するためjwtトークンを少し説明します。jwtは大きくヘッダー(header).内容(payload).署名(signature)で構成されています。その中内容(Payload)に使われる情報の一部をClaimと呼ばれ、key-value形式で構成されています。jwtは基本的に内容(Payload)に下記のような情報(Claim)を持ってます。

  • iss(Issuer): トークン発行者
  • sub(Subject): トークンのタイトル(デフォルトはuser id)
  • iat(Issued At): トークン発行日(unix timestamp)
  • exp(Expiry): トークンの有効期限
  • nbf(Not Before): トークンを使えるスタート時間
  • jti(JWT Id): JWTのユニーク識別子。 主に重複的な処理を防止するために使う。
  • prv: ユーザープロバイダクラス(User Provider class)のハッシュ。複数のguardを使うためにtymondesigns/jwt-authに追加された特別なコード。(詳しく説明はこちらへ)

この情報以外、追加的にjwtトークンに情報を追加したい時、getJWTCustomClaims()関数に戻り値(Return value)を修正します。

public function getJWTCustomClaims() {
    return [
        'firstname' => $this->firstname,
        'lastname' => $this->lastname,
        'email' => $this->email
    ];
}

guard修正

ララベル(Laravel)の認証を担当してるconfig/auth.phpファイルのguardを下記のように修正します。

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

コントローラー修正

以前のブログで生成したapp/Http/Controllers/JWTAuthController.phpコントローラーにログイン関数を追加します。

public function login(Request $request) {
    $validator = Validator::make($request->all(), [
        'email' => 'required|email|max:255',
        'password' => 'required|string|min:8|max:255',
    ]);

    if($validator->fails()) {
        return response()->json([
            'status' => 'error',
            'messages' => $validator->messages()
        ], 200);
    }

    if (! $token = Auth::guard('api')->attempt(['email' => $request->email, 'password' => $request->password])) {
        return response()->json(['error' => 'Unauthorized'], 401);
    }

    return $this->respondWithToken($token);
}

protected function respondWithToken($token) {
    return response()->json([
        'access_token' => $token,
        'token_type' => 'bearer',
        'expires_in' => Auth::guard('api')->factory()->getTTL() * 60
    ]);
}

まず、リクエスト(Request)の入力データを確認します。

$validator = Validator::make($request->all(), [
    'email' => 'required|email|max:255',
    'password' => 'required|string|min:8|max:255',
]);

if($validator->fails()) {
    return response()->json([
        'status' => 'error',
        'messages' => $validator->messages()
    ], 200);
}

そしてユーザのemailpasswordでログインさせます。

if (! $token = Auth::guard('api')->attempt(['email' => $request->email, 'password' => $request->password])) {
    return response()->json(['error' => 'Unauthorized'], 401);
}

ログインに成功したらリクエスト(Request)に関してjwtトークンをリターン(Response)します。

return response()->json([
    'access_token' => $token,
    'token_type' => 'bearer',
    'expires_in' => Auth::guard('api')->factory()->getTTL() * 60
]);

ルート連結

コントローラー(Controller)に生成したログイン関数をroutes/api.phpでURLと連携する必要があります。

Route::post('login', 'JWTAuthController@login')->name('api.jwt.login');

テスト

今まで開発したjwt認証システムのログイン機能をPostmanを使って確認します。localhost/api/loginのURLにemailpasswordを入力してPOSTでリクエスト(Request)を送ったら下記のような結果を確認することができます。

postman login api test

応答(Response)で貰ったaccess_tokenキーをhttps://jwt.io/で確認すると下記のような結果を見ることができます。

check access_key

完了

これでjwt認証システムを利用してログイン機能を実装して見ました。次のブログではaccess tokenを使ってユーザの情報を取得する方法に関して見てみます。

参考

Buy me a coffeeBuy me a coffee
Posts