REST API を使って Yellowfin に SSO (PHP 編)

#### SSO の手段
Yellowfin に SSO する方法としては、[SAML ](https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=20676653)や [JWT ]( https://wiki.yellowfin.co.jp/pages/viewpage.action?pageId=17956865)を用いたものに加え、REST API でトークンを受け渡しする方法があります。
REST API を介した SSO は [JavaScript で作成]( https://qiita.com/celery/items/dbe7ef1e44663cf3a147)することも可能ですが、今回は PHP で処理します。サーバーサイドで処理させるものなので、PHP の方が実装がシンプルになると思います。

#### リポジトリ DB への行追加
今回は、管理者権限でトークンを取得し、ログインユーザーのパスワードをトークン取得時の JSON データに含めない方法を取ります。そのためには、リポジトリ DB の configuration テーブルに 1 行追加する必要があります。

```sql:Configuration table
INSERT INTO Configuration (IpOrg, ConfigTypeCode, ConfigCode, ConfigData) VALUES (1, 'SYSTEM', 'SIMPLE_AUTHENTICATION', 'TRUE');
```

#### PHP プログラム
SSO トークンを作成するAPI は /api/rpc/login-tokens/create-sso-token です。
API の 具体的な使い方は[こちら](https://developers.yellowfinbi.com/dev/api-docs/current/#operation/createLoginTokenRPC)で説明されています。画面右の request sample 欄に、POST で受け渡す BODY データのサンプルが紹介されています。サンプルの中では "noPassword": false が定義されているため、ログインユーザーのパスワードを含める必要があります。一方で、以下のサンプルコードの中では、"noPassword": true が定義されているため、ログインユーザーのパスワード情報は含んでいません。パスワード情報が不要であるにも関わらず、パスワード欄は空にできないため、dummy の文字列を入力していますが、kanpai でも cheers でも何でも構いません。
大枠の処理の流れは、コメントアウト行で説明しています。

```php:sso_sample.php
<?php
//変数の宣言と値の定義
$authUserId = 'usera@yellowfin.bi';
$authUserPass = 'dummy';
$adminId = 'admin@yellowfin.com.au';
$adminPassword = 'test';
$time = ceil(microtime(true)*1000);
$url = 'http://localhost:8880/api/rpc/login-tokens/create-sso-token';

//POSTで受け渡すHEADERとBODYのJSONデータを作成
$header = array(
	'Authorization:YELLOWFIN ts='.$time.', nonce=123',
	'Accept:application/vnd.yellowfin.api-v2+json',
	'Content-Type:application/json;charset=UTF-8'
);

$body = array(
	'signOnUser'=>array(
		'userName'=>$authUserId,
		'password'=>$authUserPass,
		'clientOrgRef'=>'1'
	),
	'noPassword'=>'true',
	'adminUser'=>array(
		'userName'=>$adminId,
		'password'=>$adminPassword
	)
);

$header_json = json_encode($header, JSON_PRETTY_PRINT);
$body_json = json_encode($body, JSON_PRETTY_PRINT);

//Yellowfinに対してトークンを要求
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $body_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$json_result = json_decode($result);
$securityToken = $json_result->securityToken;
curl_close($ch);

//受け取ったSecurityTokenを使ってSSOできることを確認(動作検証)
$yellowfin = 'http://localhost:8080/logon.i4?LoginWebserviceId='.$securityToken;
exec('chrome.exe "'.$yellowfin.'"');
?>
```

プログラムを起動してみます。
```powershell:php
php sso_sample.php 
```
標準のログインページが表示されることなく、Yellowfin にログインできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2128512/78ca2bff-2d2c-9bb3-b2d2-6e8e1fe42568.png)


やり取りするデータの中身を確認したいときは、例えば `echo($result)` 行を追加すれば、要求に対して SecurityToken を含むデータが取得できていることが分かります。

```json:response
{"securityToken":"cf7994d58e060f013a7c63690ee02e0a","tokenId":"d69eb474-c908-48d2-907c-137abdfd575c","_links":{"logout":{"href":"/api/rpc/login-tokens/terminate-sso-token/d69eb474-c908-48d2-907c-137abdfd575c","options":["POST"]}}}
```

今回のサンプルコードの中では、ユーザー ID やパスワードをべた書きしています。
また、ブラウザを立ち上げ、受け取った SecutrityToken を使って実際に SSO するところまでをプログラムの中に含めています。
プログラムに対して必要な情報をどのように受け渡すのか、あるいは受け取った SecurityToken をどう取り扱うかなどは、環境に合わせて実装を検討する必要があります。

#### ログイン画面をリダイレクト
SSO ユーザーにはログイン画面の存在自体を知らせたくないこともあるかと思います。そんな時は、[こちら]( https://support.yellowfin.co.jp/hc/ja/articles/900007043823)を参考にログイン画面をリダイレクトする処理を施してください。

#### 最後に
SAML や JWT のトークンを扱う認証基盤が存在する場合は、これらトークンを利用することを優先いただくべきかと思います。一方で、SAML や JWT トークンの連携ができない場合には、今回紹介した方法も是非ご検討ください。
では、良いデータ分析を! Santé! Cheers!