まず、Socialiteの一般的な使い方はこちらをどうぞ。
Laravel Socialiteはすごい便利ですね。但し、標準のドライバがあれば。。。
多くの場合、標準対応の、
- Google+
あたりで事足りるのですが、ある案件で「YahooのIDに対応しろ!」と言われそうなので、調べてみました。
##独自実装までの経緯
まず、「socialite yahoo」でググッてみると、直ぐに、Yahoo用のドライバに行き着いた。どやら、Yahoo以外にも主要なサービス用のものが勢揃いしているよう。。。
とはいえ、海外サービスばかり。ご存知、Yahoo JAPANも、かなり独立性が高いので、認証の仕組みも違うかなと・・・と調べて見たところ、やはり本家とJAPANではずいぶん仕様が違うようで使えそうにありません。
独自に実装するしか無いか・・・と調べていたら、ドンピシャな記事が。
これで一安心と、喜んだのもつかの間。OAuth1.0とOAuth2.0では、少し実装の仕方が異なる感じ(記事は1.0でYahooは2.0)。
仕方がないので、調べながら実装してみると何とかemailやIdを取得できるところまでは動いたのでメモしておきます。
あまりLaravelの仕組みを理解していないままいじってるので、おかしいところがあるかもしれません。
##前提
LaravelやらSocialiteは既にインストールされていることを前提として進めます。
##実装
先人の記事にならい、app以下にSocialiteというフォルダを作り、そこで作業することにしました。もちろん、他の場所でも問題ありません。
###YahooJpProvider
1.0では、classの実装が必要なようですが、2.0では基本、Providerだけ実装すればいいようです。
他の、Providerの記述や、Yahooの仕様ページを参考に、必要なパラメーターやメソッドをオーバーライドしていきます。
YahooJpProvider.php
<?php
namespace App\Socialite;
use Laravel\Socialite\Two\AbstractProvider;
use Laravel\Socialite\Two\ProviderInterface;
use Laravel\Socialite\Two\User;
class YahooJpProvider extends AbstractProvider implements ProviderInterface
{
//scopeの区切り文字設定
protected $scopeSeparator = ' ';
//スコープ設定
protected $scopes = [
'openid',
'profile',
'email',
];
//認証用URL($stateはオプション)
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://auth.login.yahoo.co.jp/yconnect/v1/authorization', $state);
}
//token取得用URL
protected function getTokenUrl()
{
return 'https://auth.login.yahoo.co.jp/yconnect/v1/token';
}
//Token取得の際のオプション
//Basic認証と必要なPOSTパラメータを送付
public function getAccessToken($code)
{
$basic_auth_key = base64_encode($this->clientId.":".$this->clientSecret);
$response = $this->getHttpClient()->post($this->getTokenUrl(), [
//認証
'headers' => [
'Authorization' => 'Basic '.$basic_auth_key,
],
// 'form_params' => $this->getTokenFields($code),
// 直接記述
'form_params' => [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => $this->redirectUrl
],
]);
return $this->parseAccessToken($response->getBody());
}
//ユーザー情報取得
protected function getUserByToken($token)
{
//url + schema=openidが必要だった
$response = $this->getHttpClient()->get('https://userinfo.yahooapis.jp/yconnect/v1/attribute?schema=openid', [
'headers' => [
'Authorization' => 'Bearer '.$token['access_token'],
],
]);
return json_decode($response->getBody(), true);
}
//Userにパラメーターをマップ(必要に応じてその他のパラメータ追加)
protected function mapUserToObject(array $user)
{
return (new User())->setRaw($user)->map([
'id' => $user['user_id'],
'name' => $user['name'],
'email' => $user['email'],
]);
}
//token parse用の関数
protected function parseAccessToken($body)
{
return json_decode($body, true);
}
}
本質的な機能の実装はとりあえずこんな感じ。
ここで、Yahooデベロッパーネットワークにて取得・設定した情報を.envに追加しておきます。
#YahooJp
YahooJp_ID=アプリケーションID
YahooJp_SECRET=シークレット
YahooJp_CALLBACKURL=http://localhost:8000/yahoojp/callback(コールバックURL)
あとは、config/services.phpに.envパラメータとのmapを記述しておきます。
'yahoojp' => [
'client_id' => env('YahooJp_ID'),
'client_secret' => env('YahooJp_SECRET'),
'redirect' => env('YahooJp_CALLBACKURL'),
],
ここまでで主要機能の実装は完了です。
##初期化およびプロバイダのコンテナへの登録
ちょっと悩んだのが、機能を使えるようにする方法です。providerのAuthServiceProviderのbootに書くこともできるようですが、ここでは別途プロバイダクラスを用意し、サービスプロバイダに登録することにしました。
###MySocialManager
まずは、登録するクラスを用意します。
Laravel\Socialite\SocialiteManagerを継承して、yahoojpドライバの生成を記述します。
config/services.phpから必要な情報を読み込み初期化します。
MySocialManager.php
<?php
namespace App\Socialite;
use Laravel\Socialite\SocialiteManager;
class MySocialManager extends SocialiteManager{
protected function createYahooJpDriver()
{
//services.phpの設定情報を読む
$config = $this->config['services.yahoojp'];
//設定情報と共にプロバイダを生成
return $this->buildProvider(
'App\Socialite\YahooJpProvider',$config
);
}
}
###MySocialServiceProvider
次にプロバイダクラスを用意します。
Laravel\Socialite\SocialiteServiceProviderを継承します。
MySocialServiceProvider.php
<?php
namespace App\Socialite;
use Laravel\Socialite\SocialiteServiceProvider;
class MySocialServiceProvider extends SocialiteServiceProvider
{
public function register()
{
//シングルトンとしてMySocialManagerを生成
$this->app->singleton('Laravel\Socialite\Contracts\Factory',function($app){
return new MySocialManager($app);
});
}
}
###config/app.phpの編集
登録するクラスの準備ができたので、'providers' => []中にプロバイダを追加します(一部抜粋)。
App\Socialite\MySocialServiceProvider::class,
これで利用できるようになりました。
##利用してみる
では、最低限の機能チェックをしてみます。
###Route設定
ソーシャルログインボタンのクリック先となるリダイレクト用ルートと認証後、戻ってくる先(Callback)用のルートを設定します。
Route::group(['middleware' => 'web'], function () {
//Yahooログイン(ボタンのリンク先)
Route::get('yahoojp','YahooJpController@yahoojpLogin');
//認証後の戻りURL
Route::get('yahoojp/callback','YahooJpController@yahoojpCallback');
});
###Controller
コントローラーを実装します。
と入っても、ドライバさえきちんと動けば、Controller内での実装は難しくはありません。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
//追加
use Laravel\Socialite\Contracts\Factory as Socialite;
class YahooJpController extends Controller
{
//
protected $socialite;
public function __construct(Socialite $socialite)
{
$this->socialite = $socialite;
}
public function yahoojpLogin()
{
//yahooへリダイレクト
return $this->socialite->driver('yahoojp')->redirect();
}
public function yahoojpCallback()
{
//ユーザー情報を取得
$yuser = $this->socialite->driver('yahoojp')->user();
//各情報の取得
$yuser->getId();
$yuser->getName();
$yuser->getEmail();
//とりあえず表示
return $yuser->getEmail();
}
}
以上です。emailが表示されればOKです。
出来てしまえば簡単ですが、試行錯誤が必要でした。