Laravel SocialiteをベースにしてLaravelにLINE loginを実装するための手順
Laravelにはオフィシャルパッケージとして Socialite というのが用意されています。これを使うと Facebook, Google, linkedIn, GitHub, Bitbucket といったサービスでの OAuth 認証を簡単に実装してくれます。プロバイダーとして使えるサービスはこれ以外にもたくさんあって、Socialite Providers にいくと有名どころのサービスのプロバイダーがもれなく用意されています。残念ながら LINE の OAuth 認証がこのリストになかったので、自分で用意することになりました。ということで Laravel に LINE login を実装する手順をまとめてみました。ここでは Laravel 側の手順を説明するため、LINE 側でのビジネスアカウントの作成、チャンネルの作成、LINE Login の有効化までは終わっているものとします。
目次
Laravel プロジェクトの作成
Laravel がないと始まらないので、global にインストールした laravel を
laravel new example
で new します。
Laravel Socialite のインストールと LINE 用アダプターの追加
composer require laravel/socialite
で Socialite を追加します。composer require
が終わったら、SOcialiteにLINE用のアダプターを追加します。まずは vendor/laravel/socialite/src/SocialiteManager.php
に以下のプライベートメソッドを実装します:
<?php
/**
* Create an instance of the specified driver.
*
* @return \Laravel\Socialite\Two\AbstractProvider
*/
protected function createLineDriver()
{
$config = $this->app['config']['services.line'];
return $this->buildProvider(
'Laravel\Socialite\Two\LineProvider', $config
);
}
さらに vendor/laravel/socialite/src/Two/LineProvider.php
を以下の内容で作成します:
<?php
namespace Laravel\Socialite\Two;
use Exception;
use Illuminate\Support\Arr;
class LineProvider extends AbstractProvider implements ProviderInterface
{
/**
* The scopes being requested.
*
* @var array
*/
protected $scopes = [];
/**
* {@inheritdoc}
*/
protected function getAuthUrl($state)
{
return $this->buildAuthUrlFromBase('https://access.line.me/dialog/oauth/weblogin', $state);
}
/**
* {@inheritdoc}
*/
protected function getTokenFields($code)
{
return [
'grant_type' => 'authorization_code',
'client_id' => $this->clientId,
'client_secret' => $this->clientSecret,
'code' => $code,
'redirect_uri' => $this->redirectUrl,
];
}
/**
* {@inheritdoc}
*/
protected function getTokenUrl()
{
return 'https://api.line.me/v1/oauth/accessToken';
}
/**
* {@inheritdoc}
*/
protected function getUserByToken($token)
{
$userUrl = 'https://api.line.me/v1/profile';
$response = $this->getHttpClient()->get(
$userUrl, $this->getRequestOptions($token)
);
$user = json_decode($response->getBody(), true);
return $user;
}
/**
* {@inheritdoc}
*/
protected function mapUserToObject(array $user)
{
return (new User)->setRaw($user)->map([
'id' => $user['mid'],
'name' => $user['displayName'],
'nickname' => $user['displayName'],
'email' => null,
'avatar' => $user['pictureUrl'],
'avatar_original' => $user['pictureUrl'],
]);
}
/**
* Get the default options for an HTTP request.
*
* @return array
*/
protected function getRequestOptions($token)
{
return [
'headers' => [
'Authorization' => 'Bearer '.$token,
],
];
}
}
Socialite側の修正は以上です。
Laravel Socialite を Laravel 側で有効化させる
次は Socialite の Laravel 側の設定です。config/app.php
に SocialiteServiceProvider
を登録します:
<?php
// ...
'providers' => [
// Other service providers...
Laravel\Socialite\SocialiteServiceProvider::class,
],
// ...
同じファイルに定義されているエイリアス配列に Socialite ファサードを追加します:
<?php
// ...
'aliases' => [
// Other aliases...
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
],
// ...
.env に LINE Login の Channel ID, Channel Secret, Callback URL を追加します:
LINE_CHANNEL_ID=[Channel ID]
LINE_CHANNEL_SECRET=[Channel Secret]
LINE_CALLBACK_URL=[Callback URL]
[Channel ID]
, [Channel Secret]
, [Callback URL]
には取得したものを入力してください。
config/services.php
にクレデンシャルを追加します:
<?php
// ...
'line' => [
'client_id' => env('LINE_CHANNEL_ID'),
'client_secret' => env('LINE_CHANNEL_SECRET'),
'redirect' => env('LINE_CALLBACK_URL'),
],
// ...
以上で Socialite での LINE ログイン実装の準備が終わりました。
デフォルトのモデルの修正
最低限の実装をするために、デフォルトで用意されている app/User.php
の User
モデルを修正します:
<?php
// ...
protected $fillable = [
'name', 'mid', 'avatar',
];
// ...
protected $hidden = [
'mid', 'remember_token',
];
// ...
マイグレーションもあらかじめ用意されている database/migrations/2014_10_12_000000_create_users_table.php
を修正します:
<?php
// ...
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('mid')->unique();
$table->string('avatar');
$table->rememberToken();
$table->timestamps();
});
}
// ...
モデルとマイグレーションの修正が終わったら、php artisan migrate
でデータベースを用意してmigrateします。これでデータベース内にしかるべきテーブルが作成されます。
コントローラの追加
モデルの次はコントローラにルーターを追加します。OAuth provider へリダイレクトするためのルーターと、認証された後にコールバックを受け取るルーターの二つが必要となります。app/Http/Controllers/AuthController.php
に以下の内容を記述します:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Socialite;
class AuthController extends Controller
{
/**
* Redirect the user to the LINE authentication page.
*
* @return Response
*/
public function redirectToProvider()
{
return Socialite::driver('line')->redirect();
}
/**
* Obtain the user information from LINE.
*
* @return Response
*/
public function handleProviderCallback()
{
try {
$user = Socialite::driver('line')->user();
} catch (Exception $e) {
return redirect()->intended('/');
}
$authUser = $this->findOrCreateUser($user);
Auth::login($authUser, true);
return redirect()->intended('dashboard');
}
/**
* Logout
*
* @return Response
*/
public function logout()
{
Auth::logout();
return redirect()->intended('/');
}
/**
* Return user if exists; create and return if doesn't
*
* @param object $user
* @return User
*/
private function findOrCreateUser($user)
{
if ($authUser = \App\User::where('mid', $user->id)->first()) {
return $authUser;
}
return \App\User::create([
'mid' => $user->id,
'name' => $user->name,
'avatar' => $user->avatar
]);
}
}
ログアウト用の処理も追加してあります。上記のログイン処理、ログイン後のコールバック処理に加えて、ログイン後のダッシュボード用のコントローラも用意します:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('dashboard');
}
}
コンストラクタで auth
ミドルウェアを呼び出すことで、ログインしていないユーザが dashboard
にアクセスできないようにしています。
ルーターの追加
routes/web.php
にルーターを追加します:
<?php
// ...
Route::get('/', function () {
return view('welcome');
});
Route::get('dashboard', 'DashboardController@index');
Route::get('login', 'Auth\AuthController@redirectToProvider')->name('login');
Route::get('callback', 'Auth\AuthController@handleProviderCallback');
Route::post('logout', 'Auth\AuthController@logout')->name('logout');
// ...
ビューの作成
最後にビューを作成します。とりあえず最低限ということで、まずはログインボタンを設置するトップページとして、デフォルトの welcome.blade.php
を触ります:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>LINE Login</title>
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
<style>
html, body {
background-color: #fff;
color: #636b6f;
font-family: 'Raleway', sans-serif;
font-weight: 100;
height: 100vh;
margin: 0;
}
.full-height {
height: 100vh;
}
.flex-center {
align-items: center;
display: flex;
justify-content: center;
}
.position-ref {
position: relative;
}
.top-right {
position: absolute;
right: 10px;
top: 18px;
}
.links > a {
color: #636b6f;
padding: 0 25px;
font-size: 12px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}
</style>
</head>
<body>
<div class="flex-center position-ref full-height">
@if (Route::has('login'))
<div class="top-right links">
@if (Auth::check())
<a href="{{ url('/dashboard') }}">Dashboard</a>
@endif
</div>
@endif
<div class="title m-b-md">
<a href="{{ url('/login') }}"><img src="images/btn_login_base.png"></a>
</div>
</div>
</body>
</html>
LINE のログインボタン用の画像は LINE の開発者ページからダウンロードしてきて、public/images
ディレクトリを作成して画像ファイルを入れておいてください。
もう一つ必要なのが、ログイン後のダッシュボード画面です。これも最低限ということでこんな感じです:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<link href="/css/app.css" rel="stylesheet">
</head>
<body>
<div id="app">
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="{{ url('/') }}">
{{ config('app.name', 'Laravel') }}
</a>
</div>
<div class="nav navbar-nav navbar-right">
<form style="padding:7px 0" action="{{ url('/logout') }}" method="POST">
{{ csrf_field() }}
<button class="btn btn-link" type=submit>Logout</button>
</form>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Dashboard</div>
<div class="panel-body">
Logged in as {{ Auth::user()->name }}!
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
ログインしてみる
php artisan serve
でローカルサーバを立ち上げて、ブラウザで http://localhost:8000 へアクセスしたら、LINE login ボタンをクリックしてください。LINE のログイン画面が現れるので、メールアドレスとパスワードを入力して LOGIN をクリックすると http://localhost:8000/dashboard へ飛んでダッシュボードが表示されると思います。