LaravelのSocialiteとPassportを使ってWeb APIの認証機能を実装した話
現在開発中のアプリで、LaravelのSocialiteとPassportを使って認証機能を実装したので、その内容をまとめておきます。
設計
シーケンス
アプリも踏まえた全体のシーケンスは下図の通りです。(認可サーバ=Facebook等のサーバと捉えてください。)
アクセストークンが2種類出てきますが、それぞれの役割は下記の通りです。
- アクセストークン(SNS):認可サーバから取得する有効期限の長いトークンです。今回はリフレッシュトークン(アクセストークンを再発行する際に必要なトークン)として使用します。
- アクセストークン(Passport):クライアント⇆APIサーバでの認証に使用する有効期限の短いトークンです。上記のSNSトークンの妥当性確認後、APIサーバで発行します。
今回は、サーバ側の処理についてのみ触れるため④と⑥の実装方法について記載します。④ではLaravelのSocialite(ソーシャルログインを簡単に実装するための機能)、⑥ではLaravelのPassport(API認証を簡単に実装するための機能)を使います。
なぜソーシャルログインを使うのか?
ソーシャルログインを使用せず、独自の認証機能を実装しても良いのですが、ユーザにとって以下3つのメリットがあると考えています。
- 信頼性がそこまで高くないアプリにパスワードなどを登録せずに済む。
- 氏名や居住地などの基本情報を流用できる。(アプリケーションの設定次第ですが)
- SNSにログイン済みであれば、ログイン情報(メールやパスワード等)の入力等が不要。
Socialite
設定
ドキュメントに記載してある通りですが、一応。
【Socialiteのインストール】
composer require laravel/socialite
【.env】
Client IDやClient SecretをFacebook等のDeveloperページから取得し、以下のように設定します。(事前にアプリの登録が必要。)
FB_CLIENT_ID="FacebookのClient ID"
FB_CLIENT_SECRET="FacebookのClient Secret"
【config/services.php】
'facebook' => [
'client_id' => env('FACEBOOK_CLIENT_ID'), // FacebookのClient ID
'client_secret' => env('FACEBOOK_CLIENT_SECRET'), // FacebookのClient Secret
],
機能実装
【LoginController.php】
クライアントから送られたトークンが妥当であれば、下記を記載するだけでFacebookに登録されているユーザ情報を取得できます。
$socialUser = Socialite::driver('facebook')->userFromToken('アプリから送られたトークン');
// $socialUser-> とすればFacebookで登録している名前を取得できる
Passport
設定
こちらも、ドキュメントに記載してある通りです。
【Passportのインストール】
composer require laravel/passport
php artisan migrate
php artisan passport:install
【AuthServiceProvider】
アクセストークンの管理のルートを登録します。
public function boot()
{
$this->registerPolicies();
//以下を追記
Passport::routes();
}
【config/auth.php】
api認証のdriverオプションをpassportへ変更します。
'guards' => [
'api' => [
'driver' => 'passport', // token→passportへ変更
'provider' => 'users',
],
],
機能実装
【LoginController.php】
Passportで発行できるアクセストークンにはいくつか種類がありますが、今回はパーソナルアクセストークンを使います。
以下では、Facebookから取得した名前を持つユーザのインスタンスを生成しそのユーザに対してトークンを発行しています。
// ユーザの作成
$user = App\User::create(['name' => $socialUser->name]);
// パーソナルアクセストークンの発行
$token = $user->createToken('hilcra')->accessToken
あとは、この結果をクライアントに返して、リクエスト時にこのトークンをヘッダーにくっつけて送ってもらいます。(ここでは、詳細の説明は省きます。)
パーソナルアクセストークンの有効期限設定
これで、一通りの機能実装が完了し、あとはトークンの有効期限を設定するだけだと思っていると、ドキュメントに以下の記載が見つかりました。
パーソナルアクセストークンを使用した場合、有効期限は設定できないとのこと。
ただ、いろいろ調べて思考錯誤していると、無事設定することができました。以下、ご参考までに。
結論から言うと、PassportServiceProviderクラスのregisterAuthorizationServerというメソッドをオーバーライドすると有効期限を設定可能です。
【App/Providers/HogePassportServiceProvider.php】※各自クラスを作成ください
class HogePassportServiceProvider extends PassportServiceProvider
{
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
parent::boot();
}
/**
* Register the application services.
*
* @return void
*/
public function register()
{
parent::register();
}
/**
* Register the authorization server.
*
* @return void
*/
protected function registerAuthorizationServer()
{
$this->app->singleton(AuthorizationServer::class, function () {
return tap($this->makeAuthorizationServer(), function ($server) {
$server->enableGrantType(
$this->makeAuthCodeGrant(), Passport::tokensExpireIn()
);
$server->enableGrantType(
$this->makeRefreshTokenGrant(), Passport::tokensExpireIn()
);
$server->enableGrantType(
$this->makePasswordGrant(), Passport::tokensExpireIn()
);
// ★以下で設定
$server->enableGrantType(
new PersonalAccessGrant, new DateInterval('PT30M')
);
$server->enableGrantType(
new ClientCredentialsGrant, Passport::tokensExpireIn()
);
if (Passport::$implicitGrantEnabled) {
$server->enableGrantType(
$this->makeImplicitGrant(), Passport::tokensExpireIn()
);
}
});
});
}
}
プロバイダを新規で作成したので、config/app.phpへの追加も忘れずに。
【config/app.php】
'providers' => [
App\Providers\HogePassportServiceProvider::class,
]
-
前の記事
Laravel APIの自動テストを運用してみた話 2018.08.12
-
次の記事
Google HomeとeRemoteを使って家電を音声操作する(前編) 2019.01.06