MetabaseAPIでGoogle認証をするまで

Metabaseに登録されているネイティブクエリを全件取得したかった事案がありました。 MetabaseAPIなるものがあるらしいので、それを使ってみました。
APIを使用するためにはログインが必要です。ログインのAPIは以下のようになっているのですが・・・

POST /api/session/google_auth

Login with Google Auth.

PARAMS:
  • token value must be a non-blank string.
  • request

が、この token が一体何のトークンなのかさっぱりわかりません。( 調べた結果、JWTのid-tokenでした。)
ググってもあまり情報が出て来なかったので、手順をまとめてみます。

GoogleアカウントのOAuthキーを作成する

GoogleAPIsから、OAuthのクライアントIDを作成します。

設定としては、以下のとおり。

また、OAuthのクライアントIDを作成する場合は事前にOAuthの同意画面を作成しておく必要があります。
テスト用に使うので、てきとーに設定しておきます。

作成するとクライアントIDとクライアントシークレットが作成されるので、メモっておきます。

認可画面に飛ばす

MetabaseがOAuthのトークンを必要とするということは、OAuthのフローで認可画面を踏まないといけないということです。
今回はleague/oauth2-googleを使用してみました。

<?php
// index.php

require_once __DIR__ . '/vendor/autoload.php';

$provider = new \League\OAuth2\Client\Provider\Google([
    'clientId' => 'YourClientID',
    'clientSecret' => 'YourClientSecret',
    'redirectUri' => 'http://localhost/callback.php',
]);

// 認可用URIへリダイレクト
header("Location: {$provider->getAuthorizationUrl()}");

sudo php -S localhost で簡易サーバを立ち上げアクセスすると、Googleログインの画面が表示されるはずです。

トークンの取得

Googleでのログインが終わると、登録したコールバックURIに遷移します。(ここでは、 http://localhost/callback.php )
callback後に、JWTのid-tokenを取得します。

<?php
// callback.php

require_once __DIR__ . '/vendor/autoload.php';

$provider = new \League\OAuth2\Client\Provider\Google([
    'clientId' => 'YourClientID',
    'clientSecret' => 'YourClientSecret',
    'redirectUri' => 'http://localhost/callback.php',
]);

// 正常系の場合はcodeというクエリパラメータが付いてくる
assert(isset($_GET['code']));

$token = $provider->getAccessToken('authorization_code', ['code' => $_GET['code']]);
// getValue()でJWT形式の各値を取得できる
$idToken = $token->getValues()['id_token'];

認証とMetabaseAPIの利用

id-tokenを取得できたら、それを利用してMetabaseAPIを使うことができます。
/api/session/google_authのレスポンスにidというキーがあるので、これをヘッダーのX-Metabase-Sessionにセットすることで、各種APIにアクセスできます。

<?php
$guzzle = new \GuzzleHttp\Client();

// metabaseでの認証認可
$response = $guzzle->request('POST', 'https://your.metabase.url/api/session/google_auth', [
    'json' => [
        'token' => $idToken,
    ],
]);
// JSON形式でレスポンスが来るのでデコードする
$sessionData = json_decode($response->getBody()->getContents());
// 成功の場合は必ずidがある
assert(isset($sessionData->id))

// X-Metabase-Sessionに取得したIDを設定することで、各APIを使用できる
$response = $guzzle->request('GET', 'https://your.metabase.url/api/card', ['headers' => [
    'Content-Type' => '‘application/json',
    'X-Metabase-Session' => $sessionData->id,
]]);
$cards = json_decode($response->getBody()->getContents());