2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Docker+LaravelでSNSログインをやってみた

Posted at

目的

開発プロジェクトでSNSログインを行う場合、

  • SSLが必要になる事
  • ローカル専用ドメインでSSLがしたい

本番用のドメインでSSLを作成して、hosts等で本番ドメインをローカルホストにアクセスするように設定すれば良いが、それはそれで後々問題が起きそうなので、今回は

  • ローカル専用ドメインを用意
  • ローカル専用SSLを作成
  • Docker上で使用する

この条件で、開発環境の構築からLaravelでSNSログインの実装までを説明する。

前提

下記の環境で実装した。

  • ローカルはmacos
  • Dockerコンテナはnginx+phpfpm
  • DockerコンテナのnginxにローカルSSLを組み込む
  • ローカル専用ドメインはsnslogin.dev.cdeとする
  • コンテナはdocker-composeを使用する
  • UIはとりあえずbootstrapで行う

ローカルホスト側の設定

ローカル専用SSLはmkcertを使用する。
よってmacosのターミナルで

% brew install mkcert                 # mkcertをhomebrewからインストール
% mkcert --install                    # ローカルSSL初期設定
% mkcert localhost dev.cde *.dev.cde  # ローカルドメイン用のSSLを作成
% mkcert -cert-file ./snslogin_dev_cde.crt.pem \
    -key-file ./snslogin_dev_cde.key.pem snslogin.dev.cde # key,certファイルの作成

以上で、SSLの必要なファイルを作成した。
作成したファイルはSslディレクトリにコピーしておく。

nginxコンテナ

nginxコンテナの作成は下記の通りである。

services:

  nginx:
    image: nginx
    container_name: "snslogin-nginx"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./svr:/svr
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./Ssl/snslogin_dev_cde.crt.pem:/etc/nginx/conf.d/snslogin_dev_cde.cert.pem
      - ./Ssl/snslogin_dev_cde.key.pem:/etc/nginx/conf.d/snslogin_dev_cde.key.pem
      - ./weblog:/var/log/nginx
    depends_on:
      - phpfpm

  phpfpm:
    build: ./phpfpm

次にnginxコンテナ上のdefault.confにてSSLの設定を行う。

server {
    index index.php index.html;
    root /svr/app/public;

    listen       443 ssl;
    server_name  snslogin.dev.cde;

    ssl_certificate      /etc/nginx/conf.d/snslogin_dev_cde.cert.pem;
    ssl_certificate_key  /etc/nginx/conf.d/snslogin_dev_cde.key.pem;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;
    
    〜以下省略〜

Laravelの設定

ここで、一旦コンテナを起動して、Laravelの設定を行う。
phpfpmに接続して、コマンドラインから

% laravel new app
% composer require laravel/socialite 
% composer require laravel/ui
% php artisan ui bootstrap
% php artisan ui bootstrap --auth
% npm install
% npm run dev

以上を行う。
Laravelのパッケージはlaravel/socialite、laravel/uiをインストールする。
UIはbootstrapを使用し、認証スカフォールドを生成する。

テーブル設定

laravel標準のusersを使用するが、SNSログインの場合、パスワードがNULLになるため、マイグレーションを変更しておく。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password')->nullable(); // ここ。
            $table->rememberToken();
            $table->timestamps();
        });
    }
    
    〜以下省略〜

passwordをnullableしておく。
これが済めば、.envにDB接続情報を設定してから、マイグレーションを実行する。

% php artisan migrate

ルーティングとサービスの設定

まず、route/web.phpにルーティングの設定を行う。

Route::get('/login/{social}', 'Auth\LoginController@socialLogin')
    ->where('social', 'facebook|twitter');
Route::get('/login/{social}/callback', 'Auth\LoginController@handleProviderCallback')
    ->where('social', 'facebook|twitter');

SNSログインのURLとコールバックのURLを設定した。
次にサービスの設定をconfig/service.phpに記述する。

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Third Party Services
    |--------------------------------------------------------------------------
    |
    | This file is for storing the credentials for third party services such
    | as Mailgun, Postmark, AWS and more. This file provides the de facto
    | location for this type of information, allowing packages to have
    | a conventional file to locate the various service credentials.
    |
    */

    'mailgun' => [
        'domain' => env('MAILGUN_DOMAIN'),
        'secret' => env('MAILGUN_SECRET'),
        'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
    ],
〜中略〜

 // 以下を追加
    'facebook' => [
        'client_id' => env('FACEBOOK_API_ID'),
        'client_secret' => env('FACEBOOK_API_SECRET'),
        'redirect' => env('FACEBOOK_CALLBACKURL'),
    ],
];

とりあえず、facebookの設定のみを行った。
実際の値は、.envにて設定する。

コントローラとViewの編集

コントローラーは認証スカフォールドで作成されたLoginControllerを使用する。

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

// ここから
use Socialite; 
use App\User;
use Auth;
// ここまで追加

class LoginController extends Controller
{

〜中略〜
    // SNSログインのメソッド
    public function socialLogin($social)
    {
        return Socialite::driver($social)->redirect();
    }

    // SNSログインコールバックのメソッド
    public function handleProviderCallback($social)
    {
        $userSocial = Socialite::driver($social)->stateless()->user();
        $user = User::where(['email' => $userSocial->getEmail()])->first();

        if ($user) {
            Auth::login($user);
        } else {
            $newuser = new User;
            $newuser->name = $userSocial->getName();
            $newuser->email = $userSocial->getEmail();
            $newuser->save();

            Auth::login($newuser);
        }
        $uri = "/home";
        if (session()->has("login_after_url")) {   // ログイン後リダイレクト
            $uri = session("login_after_url");     
            session()->forget("login_after_url");
        }
        return redirect($uri);
    }
}

ここでは、SNSログインの開始とコールバックの処理を行う。
コールバック時にログインユーザがusersになければ、作成して、
Auth::login()にて強制ログインする。
SNSログイン開始前にセッション変数login_after_urlにログイン後のリダイレクト先URLを
設定しておくと、そのURLに遷移する。

Viewは同じく認証スカフォールドで作成されたresources/views/auth/login.blade.php
にSNSログインのリンクを記述する。

<div class="form-group row">
   <label for="name" class="col-sm-4 col-form-label text-md-right">
     Login With
   </label>
   <div class="col-md-6">
      <a href="{{ url('login/facebook')}}" 
        class="btn btn-social-icon btn-facebook">
        <i class="fa fa-facebook"></i>Facebookログイン
      </a>
   </div>
</div>

以上で、ローカル開発環境にSNSログインの組み込みは完了である。
実際に実行する前にSNS側のアプリ設定とログインコールバックのURLを設定すればOKである。

考察

意外と簡単にできたのである。
laravel/socialiteで他に何ができるかは未調査であるが、少なくともSNSログインは簡単にできたのである。
むしろdocker-compse.ymlやローカルSSLの方が大変だった。
作成したプロジェクトはGitHubにアップしたので、必要であれば参照していただきたい。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?