概要
laravel6での動作確認をそれぞれしつつGraphQLでjwt認証を実装してみました。
備忘録。
環境
- laravel 6.3.0
- lighthouse 4.5
- jwt-auth
インストール
lighthouse
composer require nuwave/lighthouse
laravel-graphql-playground
開発に便利なplaygroundもいれる
composer require mll-lab/laravel-graphql-playground
jwt-auth
composer require tymon/jwt-auth ^1.0.0
^1.0.0
じゃないと入ってくれない
ドキュメント要チェック
入れた結果
composer.json
"mll-lab/laravel-graphql-playground": "^1.1",
"nuwave/lighthouse": "^4.5",
"tymon/jwt-auth": "^1.0.0"
lighthouseとgraphql-playgroundの初期設定
lighthouse
参照: https://lighthouse-php.com/4.5/getting-started/installation.html
- 設定ファイルを作成
# providerの場所が古いバージョンとは変わっているので注意 ドキュメントを参考に
# config/lighthouse.php
php artisan vendor:publish --provider="Nuwave\Lighthouse\LighthouseServiceProvider"
laravel-graphql-playground
- 設定ファイルとviewを作成
# config/graphql-playground.php
php artisan vendor:publish --provider="MLL\GraphQLPlayground\GraphQLPlaygroundServiceProvider"
/graphql-playground
にアクセスすると実行画面が表示される
jwt-authの初期設定
- 設定ファイル
# config/jwt.php
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
- 秘密鍵の作成
# .envに追加される
php artisan jwt:secret
jwt-authで認証するModelを作成
API認証でjwtを使うために、JWTSubject
を認証するモデルに実装する。
今回はデフォルトのUserモデルを認証に使う。
implementsしてgetJWTIdentifier
とgetJWTCustomClaims
の2つのメソッドを定義
<?php
namespace App;
// ~略~
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
// ~略~
// add
public function getJWTIdentifier()
{
return $this->getKey();
}
// add
public function getJWTCustomClaims()
{
return [];
}
}
-
getJWTIdentifier
jwtトークンを取得する -
getJWTCustomClaims
jwtトークンにClaim(情報)を追加したい時にはここに追記する
// 例
public function getJWTCustomClaims()
{
return [
'email' => $this->email
];
}
config/auth.phpの修正
Guardの設定を変更
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // add
'provider' => 'users',
// 'hash' => false, つかわない
],
],
ログインするクエリを作成
php artisan lighthouse:query Login
app/GraphQL/Queries
に作成されます。
認証ロジックはあっさりとこんな感じにしてみました。
$args
にパラメータが入ってきます。
成功したらaccess_tokenを返す。
<?php
namespace App\GraphQL\Queries;
use GraphQL\Type\Definition\ResolveInfo;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;
class Login
{
public function __invoke($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
if (!$token = auth('api')->attempt(['email' => $args['email'], 'password' => $args['password']])) {
return ['error' => 'Unauthorized'];
}
return ['access_token' => $token];
}
}
schemaに定義
graphql/schema.graphql
に記述する。
デフォルトで色々書いてありますが、それは置いておいて以下のように定義してみる。
@middleware
ディレクティブでミドルウェアを定義することが出来る。
ログインなのでguest:api
ミドルウェアを適用。
type Query {
login(email: String! password: String!): LoginData @middleware(checks: ["guest:api"])
}
# 返ってくるデータのスキーマ
type LoginData {
access_token: String
error: String
}
ログインする
クエリを叩く
/graphql-playground
にて
{
login(email: "test@example.org" password: "password") {
access_token
error
}
}
実行
結果
成功
{
"data": {
"login": {
"access_token": "ここにトークン",
"error": null
}
}
}
失敗
{
"data": {
"login": {
"access_token": null,
"error": "Unauthorized"
}
}
}
認可ルートを設定
@middleware
ディレクティブを使用してauth:api
ルートを定義
type Query {
login(email: String! password: String!): LoginData @middleware(checks: ["guest:api"])
users: [User!]! @all @middleware(checks: ["auth:api"])
}
HTTP HEADERSでアクセストークンを渡す
{
"Authorization": "Bearer アクセストークン"
}
おわり
schema.graphql
を変更したら叩く
php artisan lighthouse:clear-cache