Paradigm Shift Design

ISHITOYA Kentaro's blog.

mojoliciousでOAuth2

Hi, perl apprenticeなkent013です。

Mojolicious::Liteは何となく1ファイルに全て押し込む的な発想(単に慣れてないだけ)が嫌いなので、Mojoliciousを単体で使ってみようとか思ってます。
だけど、その辺に落ちているコードはLite用で苦労してます。
ま、勉強っつーコトで。

掲題のOAuth2ですが、mojolicious素敵だからさくっとできるんだろうなー。凄いんだろうなー!
って期待してやってみましたが、Railsomniauthほどではないけど、簡単。

1, Mojolicious::Plugin::OAuth2をインストール

Mojolicious::Plugin::OAuth2をインストールするのに、

cpanm Mojolicious::Plugin::OAuth2

ってしたら、

FAIL Installing Mojolicious::Plugin::OAuth2 failed.

とか言われちゃって、Issue上げそうになりましたが、

mojo version

したら、マイナーバージョンが違ったのでアップデートしたら直りました。あぶねぇあぶねぇw

2, startupでpluginの読み込み

libの[AppName].pmのstartupに、

$self->plugin('o_auth2',
            facebook => {
              key => '[APP Key]',
              secret => '[APP Secret'
            });  

と書いておく。Liteだと、

plugin 'o_auth2',
   facebook => {
      key => '[APP Key]',
      secret => '[APP Secret]' 
   };

って、書くみたい。大分違うので戸惑う…本当はconfファイル書くべきなんだろうけど、まだよく分からないので、ペンディング。

3, ルーティング

bridgeするなら、

my $r = $self->routes;
$r->get('/auth')->to('auth#auth');
$r->get('/login')->to('auth#login');
$r->get('/logout')->to('auth#logout');

$r = $r->bridge('/')->to(cb => sub {
  my $self = shift;

  if ($self->session('login_name')) {
    return 1;
  }
  else {
    $self->redirect_to('/login');
  }
});
$r->get('/')->to('main#top');

のように、bridgeの前にlogin/logout/authを書く。authはfacebook authしてくれる奴。
名前は適当。Liteだとunderとか使うのがいいみたい。
本当は、bridgeの中でsessionがinvalidだったらreturn 1するみたいな処理も書かないといけないとおもう。

4, 認証周り

sub auth {
  my $self = shift;
  $self->get_token('facebook', callback => sub {
    my $token = shift;
    my $ua = Mojo::UserAgent->new;
    my $me = $ua->get(
      'https://graph.facebook.com/me?access_token=' . $token)->res->json;
    $self->session('login_name' => $me->{name});
    $self->session('token' => $token);
    $self->redirect_to('/');
  });
}

sub login {
  my $self = shift;
  $self->session(expires => 1);
}

sub logout {
  my $self = shift;
  $self->session(expires => 1);
  $self->redirect_to('/login');
}

logoutはセッション消してからloginに転送するだけ。 loginはログインっぽい表示するページ authはfacebookにログインしてsessionにデータ書き込んで/へ転送する。

OAuth2プラグインのgithubページによると、

get '/auth' => sub {
  my $self=shift;
  $self->get_token('facebook',callback=>sub {
    ...
  });
};

とあって、作者のMarcusさんのEasily integrating your Mojolicious app with Facebook.という記事には、

get 'hello' => sub {
  My $self=shift;
  #redirects the gets the token asynchronous
  $self->get_token('facebook', callback => sub {
    my $token=shift;
    my $me=$self->client->get(
      'https://graph.facebook.com/me?access_token='.$token)->res->json;
    $self->render( text =>
        "Hello ".$me->{name} );
  });
}

とあるんだけど、この$self->clientがそんなメソッドないぜ!っつって怒られちゃう。
むがー!!!ってなってたら、最近のmojoliciousでは、UserAgentを使うように変更されたそうで。
Mojo::Client has been deprecateでRiedelさんがいってはりました。

5, しょかん

というわけであとは、facebookAPIキーとれば動きます。
かなり簡単。イロイロ外してるところはあるかもしれませぬが。
でもサポートしてるサービスが少ないのが玉に瑕かな。まー、追々ということで。