Laravel 4でTwitterログイン機能を作ってみる

Laravel 4で、標準のAuth関連機能とTwitterのOAuth認証パッケージとを連動させて、Twitterでログイン&ユーザー登録機能を作ってみる。

Twitterのユーザー情報をそのまま自前のユーザーテーブルに保存して利用するんで、

php artisan migrate:make create_users_table

をしてmigrationファイルを生成し、以下のようなテーブルスキーマを定義する。

	public function up()
	{
		Schema::create('users', function($table) {
		    $table->integer('id')->unsigned();
		    $table->primary('id');
		    $table->string('screen_name');
		    $table->string('oauth_token');
		    $table->string('oauth_token_secret');
		    $table->timestamps();
		});
	}

	public function down()
	{
		Schema::drop('users');
	}

プライマリーキーのusers.idに、Twitterのuser_idを直接保存して利用するので、$table->increments(‘id’)にはせず(auto incrementにはせず)、unsigned intなプライマリーキーとして定義する。あと、Twitterの認証情報であるoauth_tokenとoauth_token_secretを保存するカラムも用意しておく。

Userモデルは以下のような感じ。

use Illuminate\Auth\UserInterface;

class User extends Eloquent implements UserInterface {

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

	public function getAuthPassword()
	{
		return null;
	}

}

Authで認証に利用するユーザークラスにはimplements UserInterfaceが必要なので、getAuthIdentifier()とgetAuthPassword()の二つを追加しておく。Twitter認証ではシステム独自のパスワードは必要ないのでgetAuthPassword()ではNULLを返している。

続いて、Twitter認証パッケージのTwitterOAuth Service Provider for Laravel 4をインストールする。インストール手順はドキュメント通り。composer.jsonに依存設定を追加して、composer updateしたり、config:publishしたり。

あと、dev.twitter.comでアプリケーション登録して認証キーの発行をおこない、app/config/packages/philo/twitter/config.phpにその値を登録しておく。

さてここからが実際のコーディング。Twitterログイン用のルーティング定義は以下のような感じになる。ほぼドキュメントに書かれている通り。

Route::get('login', function() {
    if (Auth::check()) {
        return Redirect::to('/')->with('message', 'ログイン済みです。');
    }
    $tokens = Twitter::oAuthRequestToken();
    Twitter::oAuthAuthorize(array_get($tokens, 'oauth_token'));
    die;
});

これで/loginにアクセスすると、Twitterの認証ページにリダイレクトする。Twitter側で認証されると呼ばれるコールバックURLは、dev.twitter.comで設定できるので、サンプルアプリの「/login/callback」に設定しておく。コールバック時の処理は以下のようになる。

Route::get('login/callback', function() {
    $token = Input::get('oauth_token');
    $verifier = Input::get('oauth_verifier');
    $accessToken = Twitter::oAuthAccessToken($token, $verifier);
    
    if (isset($accessToken['user_id'])) {
        $user_id = $accessToken['user_id'];
        $user = User::find($user_id);
        if (empty($user)) {
            $user = new User;
            $user->id = $user_id;
        }
        $user->screen_name = $accessToken['screen_name'];
        $user->oauth_token = $accessToken['oauth_token'];
        $user->oauth_token_secret = $accessToken['oauth_token_secret'];
        $user->save();

        Auth::login($user);
        
        return Redirect::to('/');
    } else {
        return Redirect::to('login')->with('message', 'Twitter認証できませんでした。');
    }
});

コールバックされたパラメータからアクセストークンを取得し、TwitterユーザーID($accessToken[‘user_id’])が取れていればログイン成功。そのTwitterユーザーIDがusersテーブルに登録されていない場合は、新しいレコードとして登録する。

screen_name、oauth_token、oauth_token_secretに関しては、ログインするたびに新しい情報に更新する。

で、Auth::login($user)がポイントで、これによってそのユーザーでログインしている状態をシステム(セッション)に記憶させる。

今回はusersテーブルに直接Twitterのログイン情報を持たせたんで、Twitter認証情報から直接Userクラスのインスタンスを取得できた。

もしも、Twitter認証情報をusersテーブル以外に持たせたい場合(通常は自前のID、パスワードでログインしつつ、必要ならばTwitterでもログインできるようにする、など)でも、最終的にUserクラス(というかUserIntafaceが実装されたクラス)のインスタンスを取得してしまえば同様にログイン処理が行える。

擬似コードとしては、以下のような感じ。

// Twitter認証テーブルから該当行を取得
$twitterUser = TwitterUser::find($accessToken['user_id']);

// Twitter認証テーブルとリンクしているUserテーブルの該当行を取得
$user = User::find($twitterUser['user_id']); 

Auth::login($user); // 該当ユーザーをログインさせる

一応ログアウト処理のルーティングも書いておく。これはTwitter認証とは関係なく、Laravel 4のログアウト処理のまま。

Route::get('logout', function() {
   Auth::logout();
   return Redirect::to('/')->with('message', 'ログアウトしました。');
});

あと、ホーム画面でログイン状況がわかるように書いておく。

Route::get('/', function()
{
	return View::make('home');
});
// app/views/home.blade.php
@if (Auth::check())
    {{{ Auth::user()->screen_name }}}ログイン中
    <a href="/logout">ログアウト</a>
@else
        未ログイン
    <a href="/login">ログイン</a>
@endif

未ログイン状態の場合は、ログインへのリンクを表示。ログイン中の場合は、ログインユーザーのscreen_nameを表示し、ログアウトリンクを表示している。

ちなみにこのTwitter認証パッケージは、Twitter APIパッケージを利用しているので、このままTwitter APIの機能を利用できる。たとえば、

$user = Auth::user();
Twitter::setOAuthToken($user->oauth_token);
Twitter::setOAuthTokenSecret($user->oauth_token_secret);
$timeline = Twitter::statusesUserTimeline($user->id);

なんて感じで、ユーザーのタイムラインを取得できる。

Laravel 4の認証処理周りはシンプルで、自前でいろいろ処理したい場合でも、なかなか使いやすそうだね。

関連する投稿: