takaya030の備忘録

PHP、Laravel、Docker などの話がメインです

Laravel の OAuth クライアントを Lumen に移植した

はじめに

下記の条件で Lumen で使える OAuth クライアントを探して手頃なものが見つからなかったので、過去に Laravel を使っていた時によく使った OAuth クライアントを移植してみました

  • Facade を使わない
  • カスタムの OAuth サービスを登録可能

作成した OAuth クライアント

こちらが今回作成したパッケージです。oriceon/oauth-5-laravel を fork して Lumen 向けに書き換えています
Lumen 6 以降で動作します

github.com

インストールおよび設定

インストール

Lumen のプロジェクトの composer.json に以下の内容を追加

"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/takaya030/oauth-lumen"
    }
],
"require": {
  "takaya030/oauth-lumen": "dev-master"
}

その後、 composer update でパッケージをインストール

$ composer update

パッケージ登録

下記内容で OAuth サービスプロバイダを作成

app/Providers/OAuthServiveProvider.php

<?php

namespace App\Providers;

/**
 * @author     Dariusz Prz?da <artdarek@gmail.com>
 * @copyright  Copyright (c) 2013
 * @license    http://www.opensource.org/licenses/mit-license.html MIT License
 */

use Illuminate\Support\ServiceProvider;
use Takaya030\OAuth\OAuth;

class OAuthServiceProvider extends ServiceProvider {
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;
    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot()
    {
    }
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        // Register 'oauth'
        $this->app->singleton('oauth', function ($app) {
            // create oAuth instance
            $oauth = new OAuth();

            // return oAuth instance
            return $oauth;
        });
    }
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [];
    }
}

boostrap/app.php に OAuth サービスプロバイダを登録

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

$app->register(App\Providers\OAuthServiceProvider::class);

設定ファイル

プロジェクトのルートに config フォルダを作成。その下に下記内容で oauth-lumen.php を配置する

config/oauth-lumen.php

<?php

return [

    /*
   |--------------------------------------------------------------------------
   | oAuth Config
   |--------------------------------------------------------------------------
   */

    /**
    * Storage
    */
    'storage' => '\\OAuth\\Common\\Storage\\Session',
    //'storage' => '\\Takaya030\\OAuth\\OAuthLumenSession',

    /**
    * Consumers
    */
    'consumers' => [

        'Google' => [
            'client_id'     => '',
            'client_secret' => '',
            'scope'         => [],
        ],

    ]

];

boostrap/app.php の中で config/oauth-lumen.php を読み込むようにする

/*
|--------------------------------------------------------------------------
| Load Custom Config Files
|--------------------------------------------------------------------------
*/

$app->configure('oauth-lumen');

認証情報

config/oauth-lumen.phpconsumers に追加する

    /**
    * Consumers
    */
    'consumers' => [

        'Google' => [
            'client_id'     => 'Your Google client ID',
            'client_secret' => 'Your Google Client Secret',
            'scope'         => ['OAuth2 scope'],
        ],  
    ]

Session Storage の設定

アクセストークンをセッションに保存するための設定
Lumen はデフォルトではセッションが有効になっていないため、下記サイトの手順で有効化する

qiita.com

config/oauth-lumen.phpstorage の設定を下記に変更

    /**
     * Storage
     */
    'storage' => '\\Takaya030\\OAuth\\OAuthLumenSession',

使い方

基本的な使い方

下記のコードで OAuth サービスクラスのオブジェクト が取得可能

$service = app('oauth')->consumer('Google');

オプションで第2引数に認証時にリダイレクト先 URL が指定できる

$service = app('oauth')->consumer('Google', 'http://url.to.redirect.to');

サンプルプログラム

Google

認証情報を config/oauth-lumen.php に追加

'Google' => [
    'client_id'     => 'Your Google client ID',
    'client_secret' => 'Your Google Client Secret',
    'scope'         => ['userinfo_email', 'userinfo_profile'],
],  

コントローラのサンプルコード

<?php

public function loginWithGoogle(Request $request)
{
    // get data from request
    $code = $request->get('code');
    
    // get google service
    $googleService = app('oauth')->consumer('Google');
    
    // check if code is valid
    
    // if code is provided get user data and sign in
    if ( ! is_null($code))
    {
        // This was a callback request from google, get the token
        $token = $googleService->requestAccessToken($code);
        
        // Send a request with it
        $result = json_decode($googleService->request('https://www.googleapis.com/oauth2/v1/userinfo'), true);
        
        $message = 'Your unique Google user id is: ' . $result['id'] . ' and your name is ' . $result['name'];
        echo $message. "<br/>";
        
        //Var_dump
        //display whole array.
        dd($result);
    }
    // if not ask for permission first
    else
    {
        // get googleService authorization
        $url = $googleService->getAuthorizationUri();
        
        // return to google login url
        return redirect((string)$url);
    }
}

カスタムの OAuth サービスの使い方

例として Google サービスDatastore API が使えるよう拡張してみます

OAuth サービスクラスの定義

Google サービスDatastore API を使うとエラーになりますが、原因はサービスクラスにスコープが定義されていないためなので Datastore のスコープを定義したサービスクラスを作成します

app/OAuth/Service/MyGoogle.php

<?php

namespace App\OAuth\Service;

use \OAuth\OAuth2\Service\Google;

class MyGoogle extends Google
{
    const SCOPE_DATASTORE = 'https://www.googleapis.com/auth/datastore';
}

OAuth サービスクラスの登録

作成したサービスクラスをサービスプロバイダで登録します

app/Providers/OAuthServiveProvider.php

<?php

namespace App\Providers;

/**
 * @author     Dariusz Prz?da <artdarek@gmail.com>
 * @copyright  Copyright (c) 2013
 * @license    http://www.opensource.org/licenses/mit-license.html MIT License
 */

use Illuminate\Support\ServiceProvider;
use Takaya030\OAuth\OAuth;

class OAuthServiceProvider extends ServiceProvider {
    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;
    /**
     * Bootstrap the application events.
     *
     * @return void
     */
    public function boot()
    {
    }
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        // Register 'oauth'
        $this->app->singleton('oauth', function ($app) {
            // create oAuth instance
            $oauth = new OAuth();

            // register custom service
            $oauth->registerService('MyGoogle', \App\OAuth\Service\MyGoogle::class);

            // return oAuth instance
            return $oauth;
        });
    }
    /**
     * Get the services provided by the provider.
     *
     * @return array
     */
    public function provides()
    {
        return [];
    }
}

OAuth サービスの設定追加

config/oauth-lumen.php

<?php

return [

    /*
   |--------------------------------------------------------------------------
   | oAuth Config
   |--------------------------------------------------------------------------
   */

    /**
    * Storage
    */
    //'storage' => '\\OAuth\\Common\\Storage\\Session',
    'storage' => '\\Takaya030\\OAuth\\OAuthLumenSession',

    /**
    * Consumers
    */
    'consumers' => [

        'MyGoogle' => [
            'client_id'     => 'Your Google client ID',
            'client_secret' => 'Your Google Client Secret',
            'scope'         => ['https://www.googleapis.com/auth/datastore'],
        ],

    ]

];

OAuth サービスオブジェクトの取得

下記のコードで Datastore API が使用可能な MyGoogle サービスオブジェクトが取得可能

$service = app('oauth')->consumer('MyGoogle');

参考

github.com

qiita.com