Laravel 5.8 Slack OAuthによるログインを実装する

SlackではOAuth 2.0認証が公開されています。
Sign in with Slack

この機能を利用して、LaravelでSlackアカウントによるSSO認証を組み込んでみます。


認証前の雛形



ログイン前の画面とログイン後に表示する画面を作成します。
ルートを追加。

・routes/web.php


  1. <?php
  2. Route::get('/login', function () {
  3.     return view('login');
  4. });
  5. Route::get('/home', function () {
  6.     return view('home');
  7. });




ログイン前の画面
・resources/views/login.blade.php


  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <meta name="viewport" content="width=device-width, initial-scale=1">
  6.         <title>ログイン</title>
  7.     </head>
  8.     <body>
  9.         <div>
  10.             <a href="{{ url('home') }}">Slackでログイン</a>
  11.         </div>
  12.     </body>
  13. </html>




ログイン後の画面
・resources/views/home.blade.php


  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <meta name="viewport" content="width=device-width, initial-scale=1">
  6.         <title>コンテンツ</title>
  7.     </head>
  8.     <body>
  9.         <div>
  10.             ログインしました
  11.         </div>
  12.     </body>
  13. </html>




ログイン画面のリンクをクリックしたらSlackのOAuth認証を実行。
ログイン後の画面に遷移する想定です。

a03_01.png

a03_02.png



Slack App



プログラムの作成前に、Slack Appを作成してOAuthのための認証情報を作成しておきます。
こちらが参考になりました。
PHPでSignin with Slackを試す

以下のリンクより認証に使用するアプリを作成します。
https://api.slack.com/apps/new

a03_03.png

作成すると、App IDやClient IDが発行されます。

a03_04.png

必要になるのは
・Client ID
・Client Secret
の2つですので控えておきます。

続いて、メニューの「OAuth & Permissions」を表示します。
「Redirect URLs」の箇所にOAuth認証後のリダイレクトを許可するURLを追加しておきます。
今回はhttp://[テストサーバー]/callbackを許可しました。

a03_05.png

これでSlack側の設定は完了です。



Laravel Socialite



Laravelにはlaravel/socialite」というOAuth認証を使用したログインを実現するためのパッケージが用意されています。
Laravel 5.3で外部アカウントを使用した認証機能を実装する方法

しかしSlackには対応していないそうで、別途自前で実装する必要があります。
Laravel 5.3のSocialiteに含まれていないLINEやYahoo!JAPANなどの認証サービスを利用する方法

Slackの実装サンプルを公開されている記事を見つけました。
Implementing Sign in with Slack using Laravel Socialite
こちらを参考に実装してみます。

まず、composerでlaravel/socialiteをインストールします。
Laravelのプロジェクトディレクトリに移動して以下のコマンドを実行。


$ composer require laravel/socialite




続いて、.envファイルを編集。
Slack Appを作成した際に取得したClient ID、Client Secret。
認証後にリダイレクトするURLを追記します。

・.evn


SLACK_CLIENT_ID=729920959312.7XXXXXXXXX
SLACK_CLIENT_SECRET=9b605bf03920887XXXXXXXXXXXX
SLACK_REDIRECT_CALLBACK_URL=http://192.168.1.103:8000/callback




services.phpで追記した.envのslackの情報が反映されるよう編集します。
・config/services.php


  1. <?php
  2. return [
  3.     /*
  4.     |--------------------------------------------------------------------------
  5.     | Third Party Services
  6.     |--------------------------------------------------------------------------
  7.     |
  8.     | This file is for storing the credentials for third party services such
  9.     | as Stripe, Mailgun, SparkPost and others. This file provides a sane
  10.     | default location for this type of information, allowing packages
  11.     | to have a conventional place to find your various credentials.
  12.     |
  13.     */
  14.     // (略)
  15.     // Slackの設定を追加
  16.     'slack' => [
  17.         'client_id' => env('SLACK_CLIENT_ID'),
  18.         'client_secret' => env('SLACK_CLIENT_SECRET'),
  19.         'redirect' => env('SLACK_REDIRECT_CALLBACK_URL'),
  20.     ],
  21. ];





Creating a custom Slack provider for Laravel Socialite



下準備の設定は終わったので、いよいよSlack認証を行うSocialiteを作成していきます。

app/Socialiteディレクトリを作成。
Socialite.phpを作成します。

・app/Socialite/Socialite.php


  1. <?php namespace App\Socialite;
  2. use Laravel\Socialite\SocialiteManager;
  3. class Socialite extends SocialiteManager
  4. {
  5.     public function createSlackDriver()
  6.     {
  7.         $config = $this->app['config']['services.slack'];
  8.         return $this->buildProvider(SlackProvider::class, $config);
  9.     }
  10. }




app/ProvidersディレクトリにSocialiteServiceProvider.phpを作成します。

・app/Providers/SocialiteServiceProvider.php


  1. <?php namespace App\Providers;
  2. use App\Socialite\Socialite;
  3. use Laravel\Socialite\SocialiteServiceProvider as SocialiteParentServiceProvider;
  4. class SocialiteServiceProvider extends SocialiteParentServiceProvider
  5. {
  6.     public function register()
  7.     {
  8.         $this->app->singleton('Laravel\Socialite\Contracts\Factory', function ($app) {
  9.             return new Socialite($app);
  10.         });
  11.     }
  12. }




最後にapp/SocialiteディレクトリへSlackProvider.phpを作成します。

・app/Socialite/SlackProvider.php


  1. <?php namespace App\Socialite;
  2. use Laravel\Socialite\Two\User;
  3. use Laravel\Socialite\Two\AbstractProvider;
  4. use Laravel\Socialite\Two\ProviderInterface;
  5. class SlackProvider extends AbstractProvider implements ProviderInterface
  6. {
  7.     /**
  8.      * {@inheritdoc}
  9.      */
  10.     protected $scopes = [
  11.         'identity.basic',
  12.         'identity.team',
  13.         'identity.email',
  14.         'identity.avatar'
  15.     ];
  16.     /**
  17.      * {@inheritdoc}
  18.      */
  19.     protected function getAuthUrl($state)
  20.     {
  21.         return $this->buildAuthUrlFromBase('https://slack.com/oauth/authorize', $state);
  22.     }
  23.     /**
  24.      * {@inheritdoc}
  25.      */
  26.     protected function getTokenUrl()
  27.     {
  28.         return 'https://slack.com/api/oauth.access';
  29.     }
  30.     /**
  31.      * {@inheritdoc}
  32.      */
  33.     protected function getUserByToken($token)
  34.     {
  35.         $options = ['headers' => ['Accept' => 'application/json']];
  36.         $endpoint = 'https://slack.com/api/users.identity?token='.$token;
  37.         $response = $this->getHttpClient()->get($endpoint, $options)->getBody()->getContents();
  38.         return json_decode($response, true);
  39.     }
  40.     /**
  41.      * {@inheritdoc}
  42.      */
  43.     protected function mapUserToObject(array $user)
  44.     {
  45.         return (new User)->setRaw($user)->map([
  46.             'id'        => \Arr::get($user, 'user.id'),
  47.             'name'     => \Arr::get($user, 'user.name'),
  48.             'email'     => \Arr::get($user, 'user.email'),
  49.             'avatar'    => \Arr::get($user, 'user.image_32'),
  50.         ]);
  51.     }
  52. }





config/app.phpを編集。
作成したSocialiteServiceProviderが利用できるよう、providersに追記します。

・config/app.php


  1. <?php
  2. return [
  3.     /*
  4.     |--------------------------------------------------------------------------
  5.     | Autoloaded Service Providers
  6.     |--------------------------------------------------------------------------
  7.     |
  8.     | The service providers listed here will be automatically loaded on the
  9.     | request to your application. Feel free to add your own services to
  10.     | this array to grant expanded functionality to your applications.
  11.     |
  12.     */
  13.     'providers' => [
  14.         // ...
  15.         //slack/socialite
  16.         App\Providers\SocialiteServiceProvider::class,
  17.     ],
  18. ];



これでSlack OAuth認証を利用する準備ができました。




アプリケーションへの組み込み



最初に作成した雛形にSlack認証を組み込んでみます。

・routes/web.php


  1. <?php
  2. Route::get('/login', function () {
  3.     return view('login');
  4. });
  5. Route::get('/home', function () {
  6.     return view('home');
  7. });
  8. Route::get('/redirect', 'OAuthController@redirectToProvider');
  9. Route::get('/callback', 'OAuthController@handleProviderCallback');




ログイン前の画面
・resources/views/login.blade.php


  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <meta name="viewport" content="width=device-width, initial-scale=1">
  6.         <title>ログイン</title>
  7.     </head>
  8.     <body>
  9.         <div>
  10.             <a href="{{ url('redirect') }}">Slackでログイン</a>
  11.         </div>
  12.     </body>
  13. </html>




ログイン後の画面
・resources/views/home.blade.php


  1. <!DOCTYPE html>
  2. <html>
  3.     <head>
  4.         <meta charset="utf-8">
  5.         <meta name="viewport" content="width=device-width, initial-scale=1">
  6.         <title>コンテンツ</title>
  7.     </head>
  8.     <body>
  9.         <div>
  10.             ログインしました
  11.         </div>
  12.     </body>
  13. </html>




OAuth認証のためのコントローラー
・app/Http/Controllers/OAuthController.php


  1. <?php
  2. namespace App\Http\Controllers;
  3. use Socialite;
  4. class OAuthController extends Controller
  5. {
  6.     
  7.     // Slack認証へ遷移
  8.     public function redirectToProvider()
  9.     {
  10.         return Socialite::driver('slack')->redirect();
  11.     }
  12.     // Slackからのリダイレクト
  13.     public function handleProviderCallback()
  14.     {
  15.         $user = Socialite::driver('slack')->stateless()->user();
  16.         return view('home', ['user' => $user]);
  17.     }
  18. }




動かしてみます。

a03_06.png

a03_07.png

a03_08.png

無事SlackのOAuthを通過し、アプリケーションに戻ってきました。
Slackから取得できる情報は以下の通り。


'id' => [Slack ID]
'nickname' => [ニックネーム]
'name' => [ユーザー名]
'email' => [ユーザーのメールアドレス]
'avatar' => [アバターの画像URL]






【参考URL】
Sign in with Slack
PHPでSignin with Slackを試す
Laravel 5.3で外部アカウントを使用した認証機能を実装する方法
Laravel 5.3のSocialiteに含まれていないLINEやYahoo!JAPANなどの認証サービスを利用する方法

関連記事

コメント

非公開コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
Symfoware まとめ

PR




検索フォーム

月別アーカイブ