Laravelでアプリケーションを構築した経験がある人ならログイン認証機能を利用することでLaravelへのユーザのアクセス制限を行えることは知っているかと思います。しかし、Laravelの外側のアプリケーションからアクセス制限のかかっているLaravel内のリソースにアクセスするためにはどうしたらいいのでしょう。そんな疑問を解決してくれるのがLaravel Passportです。

Laravel Passportを使用するとLaravel上でOAuth2.0に沿った形でAPIの認証機能を短時間で実装することができます。

OAuth2.0に沿った形でAPIの認証機能 といってもそれが何かわからないという人が大半だと思います。簡単に言えばLaravelの外側にあるアプリケーションからアクセスしたいリソースに対してアクセストークン(文字列)を使って管理するための仕組みです。

アクセス制限の行われているサービス/リソースへのアクセスはアクセストークン)というものを利用して行います。アクセストークンを持っている場合のみアクセス許可が与えられたサービス/リソースにアクセスすることが可能となります。そのためアクセスを行いたいアプリケーションにアクセストークンをどのように与えるかが重要になります。アクセストークンを与えるための複数の仕組みを持っているのがLaravel Passportです。

Laravel7まではclientとpersonal access tokensを管理するためのUIがVue Componentsの形で提供されていたのですがLaravel8ではなくなりました。
fukidashi

Laravel Passport

Laravel PassportではOAuth2.0に沿って以下の4つの認可方法を利用することができます。どれもサーバと外側のアプリケーションとのやりとりの結果、アクセストークンを取得することができます。

  • Autorization Code Grant
  • Implicit Grant ※推奨されない
  • Password Grant
  • Client Credential Grant
上記以外にもう一つPersonal Access Tokenというものがあります。これはシステムにアカウントを持つユーザが自分でアクセストークンを発行するのでサーバとの情報の交換を行った結果取得できるアクセストークンではありません。そのため上記の4つとわけています。
fukidashi

4つも方法があるので最初は難しく感じられるかもしれませんが、どれもアクセストークンをどうやって取得するのか(Laravelから見ればどうやってアクセストークンをクライアントに与えるのか)だけのシンプルな考え方なので、アクセストークンに注目すれば必ず理解できます。Laravel Passportの主役はアクセストークンです!

Laravel Passportのインストール

Laravel Passportをインストールするためには、Laravelのインストールとデータベースの作成が必要です。

Laravelのインストールと各種設定

composerコマンドでLaravelのインストールを行います。


$ composer create-project --prefer-dist laravel/laravel passport

データベースにはsqliteを利用します。データベースファイルを作成し、.envファイルを更新します。


$ touch database/database.sqlite

.envファイルを開き、DB_CONNECTIONをmysqlからsqliteに変更します。それ以外のDB_*関係の行は削除します。


DB_CONNECTION=sqlite

php arisan make:authコマンドで認証機能の追加を行います。


$ php artisan make:auth
Authentication scaffolding generated successfully.

Laravel Passportのインストール

composerコマンドでLaravel Passportのパッケージのインストールを行います。


$ composer require laravel/passport

php artisan migrateコマンドでテーブルの作成を行います。通常だとusersとpassword_resetsテーブルのみですが、Laravel Passportに関連するoauth_*テーブルが追加で作成されているのがわかります。


passport $ php artisan migrate
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (0.02 seconds)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (0 seconds)
Migrating: 2016_06_01_000001_create_oauth_auth_codes_table
Migrated:  2016_06_01_000001_create_oauth_auth_codes_table (0 seconds)
Migrating: 2016_06_01_000002_create_oauth_access_tokens_table
Migrated:  2016_06_01_000002_create_oauth_access_tokens_table (0 seconds)
Migrating: 2016_06_01_000003_create_oauth_refresh_tokens_table
Migrated:  2016_06_01_000003_create_oauth_refresh_tokens_table (0 seconds)
Migrating: 2016_06_01_000004_create_oauth_clients_table
Migrated:  2016_06_01_000004_create_oauth_clients_table (0 seconds)
Migrating: 2016_06_01_000005_create_oauth_personal_access_clients_table
Migrated:  2016_06_01_000005_create_oauth_personal_access_clients_table (0 seconds)

passport:installコマンドを実行するとトークンを作成するために使用する暗号化キーとPersonal access clientとPassword grant clientが作成されます。


$ php artisan passport:install
Encryption keys generated successfully.
Personal access client created successfully.
Client ID: 1
Client secret: jm8teSyWc1EOz7p9xcWiodA7shj83Y6rVJbH2ruJ
Password grant client created successfully.
Client ID: 2
Client secret: WJFDwSKZBJHoScIfs7WSj4gSsLtV9LU5fmLRK5p8

storageディレクトリの中にoauth-private.key, oauth-public.keyという名前でキーが保存されます。また、Client情報についてはoauth_clientsテーブルに保存されます。

Client情報はアクセストークンを取得するために必要となる情報です。Client ID 2のPassword grant clientは後ほど利用します。
fukidashi

sqliteでデータベースを作成している場合は、sqlite3コマンドでデータベースに接続し、テーブル情報を取得することができます。passport:installコマンド実行後であれば、oauth_clientsテーブルに2つの行が追加されています。


passport $ sqlite3 database/database.sqlite 
SQLite version 3.13.0 2016-05-18 10:57:30
Enter ".help" for usage hints.
sqlite> .tables
migrations                     oauth_personal_access_clients
oauth_access_tokens            oauth_refresh_tokens         
oauth_auth_codes               password_resets              
oauth_clients                  users                        
sqlite> select * from oauth_clients;
sqliteのデータベースに接続するためにはコマンドラインではなくTablePlusなどのデータベース管理ソフトを利用することも可能です。
fukidashi

UserモデルにtraitのHasApiTokensを追加します。createTokenメソッドなどTokenに関するメソッドを持っています。Userモデルのファイルはapp\User.phpです。


use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Passport\HasApiTokens;

class User extends Authenticatable
{
    use Notifiable,HasApiTokens;

AuthProvider.phpファイルのbootメソッドにPassport::routesメソッドを追加します。


namespace App\Providers;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Laravel\Passport\Passport;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        // 'App\Model' => 'App\Policies\ModelPolicy',
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        Passport::routes();
    }
}

Passport::routes()を加えて、php artisan route:listでルーティングを確認すると複数のルーティングが追加されています(URL列でoauthと入っているものすべて)。

追加されたルーティングを確認
追加されたルーティングを確認

最後にconfig/auth.phpでapi guardのdriverの設定変更を行います。初期設定ではtokenになっていますが、passportにします。


'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

トークンを使ったシンプルなアクセス制限機能はLaravelにも備わっています。その機能については下記が参考になります。

用語

Grant, Client, Scope, Token, Code

Oauth2.0の詳細についてはこの文書では説明していないため、下記の用語が急に出てくることもありますので、先に用語の確認を行っておきます。

  • Access Token(アクセストークン)とは

アクセス制限のかかったリソースに対してアクセスを行うためのトークンです。リソースとはLaravel上に保存したユーザ情報であったり、売上情報等です。

  • Grant(グラント)とは

アクセストークンを取得するための方法を表しています。例えばPassword Grantはパスワードを利用してアクセストークンを取得するという意味を表しています。

  • Client(クライアント)とは

Clientはユーザではなくアクセストークンを利用するアプリケーションのことを意味します。

  • Scope(スコープ)とは

Scopeは許可を表しており、Scopeを設定することでどのリソースに対してアクセス可能かを細かく設定することができます。

  • Authorization Code(認可コード)とは

認可の方法の中で最も重要なAutorization Code Grantで使用するものです。アクセストークンを取得するために認可サーバから一時的に提供される情報です。

  • Authorization Sever(認可サーバ)とは

アクセストークンを発行するサーバです。ここではLaravel PassportをインストールしたLaravelのことです。

前準備

ここから実際にコードを使ってアクセストークンの取得を行いますが、アクセストークン取得と取得後の処理のためにユーザ作成とGuzzleの設定を行います。

ユーザの作成

php artisan make:authコマンドを実行しているので、ユーザの作成をブラウザから行うことができます。Register画面からユーザの作成を行います。

ユーザ登録画面
ユーザ登録画面

Guzzleの設定

Laravelのマニュアルでは、GuzzleHttpを使ってアクセストークンの取得を行っているので同じようにGuzzleHttpを使用します。

Guzzleを使用することは必須ではなくcurlコマンドでも他のツールでも問題はありません。
fukidashi

以下の文書を利用してシステム上の適当なディレクトリにGuzzleパッケージをインストールし、そのディレクトリに作成するファイルからLaravelにアクセスします。

Password Grantによるトークン取得

Oauth2.0のGrantの中でも一番シンプルでわかりやすいPassword Grantについて説明を行います。Passwordという名前の通り、ユーザのパスワード情報を利用してトークンの取得を行います。

Password Grant Clientの作成

Password Grantを使用するためには、Password Grant Clientを作成する必要がありますが、インストール時にpassport:installを実行していればoauth_clientテーブルにPassword Grant Clientという名前で保存されています。

passport:installを実行していれば作成済みなので追加作成は必要ありませんが、下記のコマンドを実行すると新たなPassword Grant Clientを作成することができます。


 $ php artisan passport:client --password

 What should we name the password grant client? [Laravel Password Grant Client]:
 > 

Password grant client created successfully.
Client ID: 3
Client secret: JsnoBCzLckhjlWNOfYwUl0BrNeI9e75z2PFIV096

アクセストークンの取得

アクセストークンを取得するためには、Password Grantでは下記の情報が必要となります。

  • ユーザのメールアドレス
  • ユーザのパスワード
  • Password Grant Clientのid(client_id)
  • Password Grant Clientのsecret(client-secret)

ユーザのメールアドレスとパスワードは作成したユーザのものを利用します。Password Grant Clientのidとsecretがわからない場合は、oauth_clientsテーブルに保存されているのでそのテーブルを確認してください。

先ほどインストールしたGuzzleHttpを利用してLarvel(認可サーバ)へのアクセスを行います。Laravelとは独立したプログラムなので、これをLaravelとは別のアプリケーションだと想定してください。

grant_typeはpasswordを指定します。

grant_typeによってどの認可処理を使用するのかが決まります。passwordの場合はPassword Grantを使用することを明示しています。

認可サーバ(http://127.0.0.1.8000)の/oauth/tokenにPOSTリクエストを出しています。


<?php

require 'vendor/autoload.php';

$http = new GuzzleHttp\Client;

$response = $http->post('http://127.0.0.1:8000/oauth/token', [
    'form_params' => [
        'grant_type' => 'password',
        'client_id' => '2',
        'client_secret' => 'WJFDwSKZBJHoScIfs7WSj4gSsLtV9LU5fmLRK5p8',
        'username' => 'johndoe@example.com',
        'password' => 'password',
        'scope' => '',
    ],
]);

var_dump(json_decode((string) $response->getBody(), true));

実行するとアクセストークン(access_token)が認可サーバであるLaravelから戻されることが確認できます。


$ php token.php
array(4) {
  ["token_type"]=>
  string(6) "Bearer"
  ["expires_in"]=>
  int(31622400)
  ["access_token"]=>
  string(1071) "eyJ0eXAiOiJKV1Q......"
  ["refresh_token"]=>
  string(706) "def50200ccfa......"
}
access_token、refresh_tokenは長いので一部省略記述しています。実際は非常に長い文字列です。
fukidashi

トークンを利用してアクセス

アプリケーションはアクセストークンを入手することができました。入手したアクセストークンを利用すれば、アクセス制限がかけられているLaravel上のリソースに対してAPIを使ってアクセスすることができます。


<?php

require 'vendor/autoload.php';

$http = new GuzzleHttp\Client;

$accessToken = 'eyJ0eXAiOiJKV1Q......'; //取得したアクセストークン

$response = $client->request('GET', 'http://127.0.0.1:8000/api/user', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,
    ],
]);

var_dump(json_decode((string) $response->getBody(), true));
アクセストークンを取得するプロセスは認可方法によって異なりますが、アクセストークンを取得後にLaravelにアクセスするためのコードはどの認可方法でも同じです。
fukidashi

アクセスを行っている/api/userの処理内容は、api.phpファイルに記述されています。


Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

実行するとユーザ情報を取得することができます。


 $ php client.php
array(6) {
  ["id"]=>
  int(1)
  ["name"]=>
  string(8) "John Doe"
  ["email"]=>
  string(19) "johndoe@example.com"
  ["email_verified_at"]=>
  NULL
  ["created_at"]=>
  string(19) "2019-07-31 03:44:16"
  ["updated_at"]=>
  string(19) "2019-07-31 03:44:16"
}

もしアクセストークンに間違いがある場合は、HTTPコード401のUnauthorizedのエラーメッセージが戻されます。


`401 Unauthorized` response:
{"message":"Unauthenticated."}

Client Credentials Grantによるトークン取得

Password Grant はユーザIDとパスワードが必要でしたが、Client Credentials GrantではユーザIDとパスワードも必要がありません。そのためユーザに依存しないため、APIを経由して毎日の売上情報を取得するといったスケジュール化された処理を行うために使用することができます。

Client Credentials Grant Clientの作成

Client Credentials Grantを使用するためには、Client Credentials Grant Clientを作成する必要があります。コマンドは下記の通りです。


$ php artisan passport:client --client

 What should we name the client? [Laravel ClientCredentials Grant Client]:
 > 

New client created successfully.
Client ID: 4
Client secret: 5VTuDW0CESesZobxJoPDlQQ0tb1DVkbC2t3EKXFL

実行後、oauth_clientsテーブルに新たにClient 情報が追加されます。

middlewareの追加

app¥Http¥Kernel.phpファイルの$routeMiddlewareにCheckClientCredentialsを追加する必要があります。追加することでClient Credentials Grantを使ったアクセス制限が行えるようになります。


protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
       ・
       ・
    'client' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
];

アクセストークンの取得

作成したClient Credentials Grant Clientのclient IDとclient secretの2つを利用してアクセストークンを取得します。

grant_typeはclient_credentialsを指定します。


<?php

require 'vendor/autoload.php';

$http = new GuzzleHttp\Client;

$response = $http->post('http://127.0.0.1:8000/oauth/token', [
    'form_params' => [
        'grant_type' => 'client_credentials',
        'client_id' => '4',
        'client_secret' => '5VTuDW0CESesZobxJoPDlQQ0tb1DVkbC2t3EKXFL',
        'scope' => '',
    ],
]);

var_dump(json_decode((string) $response->getBody(), true));

実行するとアクセストークンを取得することができます。Password Grantではaccess_tokenの他にrefresh_tokenもありましたが、Clinet Credential Grantではrefresh_tokenはありません。


$ php token.php
array(4) {
  ["token_type"]=>
  string(6) "Bearer"
  ["expires_in"]=>
  int(31622400)
  ["access_token"]=>
  string(1070) "eyJ0eXAiOiJKV1Q......"
}

トークンを利用してアクセス

トークンを利用してLaravelにアクセスする前にLaravel側にトークンでアクセスを許可するルーティングを新たに追加します。ここでは/salesを追加します。api.webを開いて下記を追加しますが、middlewareは先程設定したclientを設定します。


Route::get('/sales', function (Request $request) {
	
    return '100000';

})->middleware('client');

取得したアクセストークンを使って/api/salesにアクセスします。


<?php

require 'vendor/autoload.php';

$http = new GuzzleHttp\Client;

$accessToken = 'eyJ0eXAiOiJKV1Q......'; //取得したアクセストークン

$response = $client->request('GET', 'http://127.0.0.1:8000/api/sales', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,
    ],
]);

var_dump(json_decode((string) $response->getBody(), true));

実行すると100000が表示されます。アクセストークンを使ってアクセスできていることがわかります。アクセストークンが間違っている場合は401 unauthorizeedのエラーが表示されます。


$ php client.php
int(100000)

アクセストークンを取得するClient Credentials Grant Clientはユーザ情報と一切関連がないため、ユーザ情報を使った処理には使えません(アクセストークンでアクセス直後にユーザは特定できない。しかしアクセスの後のコードでUser::find(id)等でユーザ情報を取得することは可能)。

Frontend Quickstart

Autorization Code Grantを説明する前に各ユーザがブラウザ上でClient情報とアクセストークンを取得できるようにするためVueの設定を行います。

Laravel Passportでは各ユーザがブラウザ上でclientとPersonal Access Tokenを取得できる画面を事前に用意してくれています。その画面の表示と処理を行うためにVue Componentが使われています。

Vue Componentを利用するためにVueが使える環境を構築します。

Vueに慣れていない人もここでの動作確認ではVueの知識はいりません。手順どおりに進められば設定可能です。

JavaScriptライブラリのインストール

npm installコマンドでJavaScriptライブラリのインストールを行います。


$ npm install

Vueの設定

Laravel Passportで準備しているVue Componentの下記のコマンドで作成します。


$ php artisan vendor:publish --tag=passport-components
Copied Directory [/vendor/laravel/passport/resources/js/components] To [/resources/js/components/passport]
Publishing complete.

実行後、resource ¥js¥componets¥passportディレクトリが作成され、その中に3つのvueファイルが作成されます。AuthorizedClients.vue, Clients.vue, PersonalAccessTokens.vueです。

resources¥js¥app.jsファイルに作成されたvue componentの情報を追加します。


Vue.component(
	'example-component', 
	require('./components/ExampleComponent.vue').default
);

// 追加したコンポーネント

Vue.component(
	'passport-clients',
    require('./components/passport/Clients.vue').default
);

Vue.component(
    'passport-authorized-clients',
    require('./components/passport/AuthorizedClients.vue').default
);

Vue.component(
    'passport-personal-access-tokens',
    require('./components/passport/PersonalAccessTokens.vue').default
);

次にhome.blade.phpにコンポーネントを追加します。


@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Dashboard</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    You are logged in!
                </div>
            </div>
                <passport-clients></passport-clients>
                <passport-authorized-clients></passport-authorized-clients>
                <passport-personal-access-tokens></passport-personal-access-tokens>
        </div>
    </div>
</div>
@endsection

コンパイルが必要になるのでnpm dev runコマンドを実行してください。


$ npm run dev

/homeにアクセスするとvueコンポーネントの追加によってCreate New ClientとCreate New Tokenのリンクが作成されます。ClientとPersonal Access Tokenをこの画面を通じてユーザが作成できるようになります。

Client、トークン作成コンポーネント
Client、トークン作成コンポーネント

Personal Access Tokens

ここまではアクセストークンを取得するためには、Oauth2.0のgrant typeを設定してclient idやclient secretを使ってLaravelからアクセストークンを取得していました。Personal Access TokenはOauth2.0の認可を利用するのではなくユーザが自分でアクセストークンの作成を行います。

アクセストークンの取得

Personal Access Tokenはブラウザから直接ユーザがアクセストークンを作成し、作成したアクセストークンを使ってアクセス制限されたリソースにアクセスすることができます。

/homeにアクセスしてCreate New Tokenのリンクをクリックしてください。

トークン作成画面
トークン作成画面

作成されるアクセストークンはこの画面でした表示されないのでアクセストークンの情報を保存する必要があります。

作成されたアクセストークン
作成されたアクセストークン

Closeボタンを押すと下記の画面が表示され、deleteリンクにより、アクセストークンの削除はできますが表示はできません。

アクセストークン作成後の画面
アクセストークン作成後の画面

トークンを利用してアクセス

アクセストークンを利用したアクセス方法はこれまでと同じなので詳細な説明は行いませんが、下記のコードでLaravelから情報を取得することできます。


<?php

require 'vendor/autoload.php';

$http = new GuzzleHttp\Client;

$accessToken = 'eyJ0eXAiOiJKV1Q......'; //取得したアクセストークン

$response = $client->request('GET', 'http://127.0.0.1:8000/api/user', [
    'headers' => [
        'Accept' => 'application/json',
        'Authorization' => 'Bearer '.$accessToken,
    ],
]);

var_dump(json_decode((string) $response->getBody(), true));

 Authorization Code Grantによるトークン取得

OAuth2.0で最も重要な認可の方法です。設定だけならLaravel Passportのおかげで簡単に行うことができます。この仕組みの理解はAPIを使う上で不可欠なので、この機会に他の文書等も使いながらOAuth2.0の理解を深めてください。

Authorization Code GrantではClient作成時に指定するRedirect URLに認可サーバのLaravelからAuthorization Code(認可コード)が送られてきます。この認可コードがなければアクセストークンを取得することができません。

そのコードを受け取る処理が必要となるため、Laravel passportをインストールしたLaravelとは別にクライアント用のLaravelを用意して動作確認を行っています。通常はLaravelではなくLaravelへアクセスを行いたいアプリケーション側で開発を行う部分です。

Laravelを使用する必要はありません。Laravelを使用しない場合はredirect_urlで指定したURLで認可サーバから戻されるコードの処理ができる環境であれば問題ありません。
fukidashi

クライアント用Laravelの設定


$ composer create-project --prefer-dist laravel/laravel passport_client

GuzzleHtttpを利用するのでcomposerでパッケージのインストールを行っておきます。


$composer require guzzlehttp/guzzle

データベースもユーザも必要ないので、設定は以上で終了です。

認可サーバとして動作しているLaravelとポート番号が被らないように8080で起動します。


 $ php artisan serve --port=8080
Laravel development server started: <http://127.0.0.1:8080>

2つのLaravelが存在して混乱するかもしれないので、Laravel Passportが動くLaravelを認可サーバ、クライアント用のLaravelをアプリケーションLaravelとします。

Clientの作成

認可サーバのLaravelの/home画面から新しいClientを作成します。作成したユーザでログインを行っておく必要があります。作成したClient情報は作成したユーザと紐づきます。

Rediret URLには、アプリケーションLaravel側のURLを設定してください。ここではhttp://127.0.0.1:8080/callbackを指定しています。

新しいClientの追加
新しいClientの追加

作成が完了すると下記のように作成したClientの情報が表示されます。表示されているidとsecretを利用します。

新しいClientを作成した後の画面
新しいClientを作成した後の画面

作成した情報はoauth_clientsテーブルに保存されます。oauth_clientsテーブルのuser_id列には作成したユーザのidが保存されます。

Client側の設定

アプリケーション側のアプリケーションLaravelのルーティング設定を行います。web.phpファイルを開いてAuthorization Code(認可コード)を取得するためのコードを記述します。


Route::get('/redirect', function () {
    $query = http_build_query([
        'client_id' => '5',
        'redirect_uri' => 'http://127.0.0.1:8080/callback',
        'response_type' => 'code',
        'scope' => '',
    ]);

    return redirect('http://127.0.0.1:8000/oauth/authorize?'.$query);
});

client_idには先程認可サーバのLaravel側で取得したClientのidの5を設定しています。redirect_uriは先程Clientを作成する際に指定したURLです。

ここでは直接client_idをコードに設定していますが開発するアプリケーションによってclient_id, client_secretを保存する場所を作成してそこから取り出して設定するといった処理が必要になります。
fukidashi

response_typeでcodeを指定しています。認可サーバから戻される値が認可コードであることを表しています。

redirectメソッドで認可サーバ側のURLを指定しています。

web.phpへの追加が完了したら、アプリケーションLaravelの/redirectへブラウザからアクセスします。

URLにhttp://127.0.0.1:8080/redirectを入力するとリダイレクトが行われ、認可サーバのLaravel側のログイン画面が表示され、ユーザのメールアドレスとパスワードが聞かれるので、Clientを作成したユーザのメールアドレスとパスワードを入力してください。

ログイン画面で項目に入力
ログイン画面で項目に入力

メールアドレスとパスワードを使ってログインができればアクセスを許可するかどうか確認の画面(認可リクエスト)が表示されます。

Client is requesting permission to access your account.

クライアントはあなたのアカウントにアクセスするための許可をリクエストしています。

アクセス許可の確認画面
アクセス許可の確認画面

Authorizeボタンをクリックするとredirect_urlで指定したページにAuthorizatino Code(認可コード)が渡されるため、それを受け取るルーティングをアプリケーションLaravelで設定しておく必要があります。

web.phpファイルを開いてルーティングcallbackを追加します。


Route::get('/callback', function () {

    $http = new GuzzleHttp\Client;

    $response = $http->post('http://127.0.0.1:8000/oauth/token', [
        'form_params' => [
            'grant_type' => 'authorization_code',
            'client_id' => '5',
            'client_secret' => 'afFF3O1AqiEblgMIq2bnVAo8dhclOUeIkrSZeePa',
            'redirect_uri' => 'http://127.0.0.1:8080/callback',
            'code' => request()->code
        ],
    ]);

    return json_decode((string) $response->getBody(), true);
});

認可サーバのLaravel側から認可コードが送られてくるので、その値をrequest()->codeで取得しています。

取得した認可コードを使って再度認可サーバへPOSTリクエストを送っています。POSTリクエストから戻ってくるレスポンスにアクセストークンが入っています。

grand_typeはauthorization_codeを設定し、作成したClientのidとsecretを指定しています。

/callbackの設定が完了した後にAuthorizeボタンをクリックして許可するとアクセストークンがブラウザに表示されます。

アクセス許可の確認画面
アクセス許可の確認画面
アクセストークン取得画面
アクセストークン取得画面

このアクセストークンを使用すればこれまでと同様にアクセス制限されたリソースにAPIでアクセスすることができます。

Implicit Grantによるトークンの取得

Implicit Grantは、Authorization Code Grantとほぼ同じ処理を行います。しかし、大きな違いはImplicit Grantでは認可サーバから認可コードが戻されません。

Implicit Grantはセキュリティ的にも問題があるため使用が推奨されていません。

Implicit Grantを使用するためには、AuthServiceProviderのbootメソッドの中にenableImplicitGrantメソッドを追加します。


public function boot()
{
    $this->registerPolicies();

    Passport::routes();

    Passport::enableImplicitGrant();
    
}

Authorization Code Grantと同様にredirectのルーティングを追加しますが、response_typeにtokenを指定します。


Route::get('/redirect', function () {
    $query = http_build_query([
        'client_id' => '5',
        'redirect_uri' => 'http://127.0.0.1:8080/callback',
        'response_type' => 'token',
        'scope' => '',
    ]);

    return redirect('http://127.0.0.1:8000/oauth/authorize?'.$query);
});

URLにhttp://127.0.0.1:8080/redirectを入力すると認可サーバのLaravel側のログイン画面が表示され、ユーザのメールアドレスとパスワードが聞かれるので、Clientを作成したユーザのメールアドレスとパスワードを入力してください。

ログイン画面で項目に入力
ログイン画面で項目に入力

Loginボタンを押しメールアドレスとパスワードに問題がなければアクセストークンがURLフラグメントの形で戻されます。


http://127.0.0.1:8080/callback#access_token=eyJ0eXAiOiJ......

アクセストークンの値を取り出すためにはJavaScriptを利用して行います。

まとめ

OAuth2.0を使用してアクセストークンを付与するサービスを開発することはあまりないかとしれませんが、アクセストークンを付与される側の開発を行う機会は今後も増えてくるかと思います。Authorization Code Grantの流れが理解できていれば開発もスムーズに進むかと思います。今回学んだことをぜひその機会に活用してください。