LaravelでOpenIDを使ってSteamに接続してみる

この記事は「mikage-labアドベントカレンダー」の12日目の記事です。

前回の続きです。

OpenIDを使ってSteamに接続してみます。

Steam authentication for Laravel 5 というパッケージを見つけたのでこれを利用しようと思います。

GitHub - invisnik/laravel-steam-auth: Laravel Steam Auth

Usage Example見ながら作ります。 勉強がてら若干アレンジします。

まずはルーティングを決めます。こんな感じですかね。

メソッド URL コントローラ アクション 備考
GET / AppController index メインページ
GET auth/login AuthController redirectTpSteam ログイン (Steamへリダイレクト)
GET auth/handle AuthController handle Steamからのコールバック
DELETE auth/logout AuthController logout ログアウト

routes/web.php

<?php 
Route::get('/', 'AppController@index');
Route::get('auth/login', 'AuthController@redirectToSteam');
Route::get('auth/handle', 'AuthController@handle');
Route::delete('auth/logout', 'AuthController@logout');

Route::{メソッド}({URL}, '{コントローラ}@{アクション}')

で{URL}を{メソッド}でアクセスしたとき{コントローラ}クラス内の{アクション}メソッドが実行されます。

CakePHPでは特別な設定をしなければ、Controller名とアクション名からURLが自動的に生成されます。

例:AppsControllerのviewメソッドがあればURLは apps/view となる

しかし、LaravelにはCakePHPのようなController名によるルーティングは無さそうです。

ルーティングに関しては、CakePHPの「設定より規約」なスタンスと違って、Laravelは言うなれば「規約より設定」なスタンスを取っていることが伺えます。

どちらにしろ、URLはメソッドも含め詳しく決めることになるので、自分の思ったとおりにルーティングできる分、Laravelのルーティングのほうが良さそうですね。

次行きましょ。ルーティングを変更したのでconfig/steam-auth.phpも変更。

リダイレクト先を/auth/steam/handleから/auth/handleに変更します。

config/steam-auth.php

<?php
return [
    /*
     * Redirect URL after login
     */
    'redirect_url' => '/auth/handle',
    /*
     *  API Key (set in .env file) [http://steamcommunity.com/dev/apikey]
     */
    'api_key' => env('STEAM_API_KEY', ''),
    /*
     * Is using https?
     */
    'https' => false
];

AuthControllerはこんな感じで作ります。

Usage Exampleとの違いはDBを使わずにユーザデータだけセッションに登録するところです。

アプリケーション独自のデータを作るわけでもないのでミニマルでいきます。

app/Http/Controllers/AuthController.php

<?php
namespace App\Http\Controllers;

use Invisnik\LaravelSteamAuth\SteamAuth;
use Illuminate\Http\Request;
use App\User;
use Auth;

class AuthController extends Controller
{
    /**
     * SteamAuth
     *
     * @var SteamAuth
     */
    protected $steam;

    /**
     * ログイン/ログアウト後リダイレクト先URL
     *
     * @var string
     */
    protected $redirectURL = '/';

    /**
     * コンストラクタ
     * 
     * @param SteamAuth $steam
     */
    public function __construct(SteamAuth $steam)
    {
        $this->steam = $steam;
    }

    /**
     * Steamのユーザ認証ページへリダイレクトする
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function redirectToSteam()
    {
        return $this->steam->redirect();
    }

    /**
     * ユーザ情報を取得する
     * セッションにユーザー情報を登録
     *
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function handle(Request $request)
    {
        if ($this->steam->validate()) {
            $info = $this->steam->getUserInfo();

            if (!is_null($info)) {
                $request->session()->put('user', $info->attributes());
                return redirect($this->redirectURL)->with('success', 'ログインしました。'); // redirect to site
            }
        }
        return $this->redirectToSteam();
    }

    /**
     * ログアウトする
     * セッションを破棄するだけ
     * 
     * @param Request $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function logout(Request $request) {
        $request->session()->flush(); 
        return redirect($this->redirectURL)->with('success', 'ログアウトしました。'); // redirect to site
    }
}

AppControllerを作って、ログインしたユーザーのゲーム一覧を表示するようにしたいので…

app/Http/Controllers/AppController.php

<?php
namespace App\Http\Controllers;

use Illuminate\Support\Facades\Config;
use App\User;
use Illuminate\Http\Request;
use GuzzleHttp\Client as GuzzleClient;
use Auth;

class AppController extends Controller
{
    /**
     * GuzzleClient
     * @var GuzzleClient
     */
    private $guzzleClient;

    /**
     * SteamAPIキー
     *
     * @var string
     */
    private $apiKey;

    public function __construct()
    {
        $this->guzzleClient = new GuzzleClient;
        $this->apiKey = Config::get('steam-auth.api_key');
    }

    /**
     * アプリメイン画面
     * 
     * @param Request $request
     */
    public function index(Request $request)
    {
        // ユーザ情報を取得
        $user = $request->session()->get('user');

        // ユーザ情報がなければ、index Viewを表示
        if ($user === null) return view('index');

        // ゲーム情報を取得
        $games = $this->getOwnedGames($user['steamID64']);
        return view('log', ['user' => $user, 'games' => $games]);
    }

    /**
     * ユーザの持っているゲームを取得する
     *
     * @param string $steamId
     * @return array ゲーム情報リスト
     */
    private function getOwnedGames($steamId)
    {
        $url = 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?key=' . $this->apiKey . '&steamid=' . $steamId . '&format=json&include_appinfo=1';
        $response = $this->guzzleClient->get($url);
        $json = json_decode($response->getBody(), true);
        return $json['response']['games'];
    }
}

Viewを適当に作ります。

ログイン前はこんな感じ。

f:id:gunsou_911:20181212221239p:plain

ログインするとこんな感じになります。

f:id:gunsou_911:20181212224307p:plain

ふむー

f:id:gunsou_911:20181212224443p:plain

ちゃんとログアウトもできます。

f:id:gunsou_911:20181212224537p:plain

たーのしー!

今日はここまでにしましょう。

次回はDI(Dependency Injection:依存性の注入)を使って遊んでみます。

CakePHPにはない要素なので楽しみ。

それではー