Keycloakを使って、GrowiのSAML認証を使ってみた 

# SAMLを実装しようと思った目的・背景
- [インフラ勉強会](https://wp.infra-workshop.tech) において、使われているWordpressとGrowi Wikiの認証を共通化して、Single Sign On(SSO)を実装しようと思ったため。
- 実装までの変遷は下の方に記載しておきます。

# 検証した最終バージョン
- Keycloak ver.4.0.0 Final (※構築済みとする)
- Growi ver.3.2.4 (※構築済みとする)
- Docker ver.18.03.1-ce
- Docker-compose ver.1.21.2

# 設定項目
## Growi
1. Growiにおいて、Admin権限で**管理**を開きます。
- アプリの設定
    - サイトURL: https://wiki.examle.com
        - ここは環境変数として、セキュリティ設定でも使われているので大事な設定です。
    <img src="https://qiita-image-store.s3.amazonaws.com/0/291673/96abbcbe-86bd-a048-fad8-cfa0f87f8655.png" alt="image.png" width="500" height="250">
 - セキュリティ設定
     - Passport 認証機構: 有効化
     - SAML: ON
2. Growiにおいて、[更新]ボタンを押す
3. Growiにおいて、コールバックURLをメモする。
    <br clear="left"><img src="https://qiita-image-store.s3.amazonaws.com/0/291673/ab475f26-f4b3-1788-ad35-347f0138982f.png" alt="image.png" width="500" height="350">

## Keycloak
4. Keycloakにおいて、Growi用のRelmを作成する。
    - Name: wiki (任意)
5. Keycloakにおいて、Growi用のRelmを作成する。
    - 言語設定(日本語)をしたい方は、 Realm Settings --> Theme
        - Internationalization Enabled: ON
        - Default Locale: ja
6. Keycloakにおいて、クライアントを追加する。
    - 右端にある[作成]ボタンから追加
        - クライアントID: wiki.examle.com
        - クライアントプロトコル: saml
        - クライアント SAML エンドポイント : https://wiki.examle.com/passport/saml/callback
            - GrowiのセクションでメモしたコールバックURL
7. Keycloakにおいて、クライアントの設定をする。   
    ※設定は最低限であるため、必要に応じてカスタマイズしてください。
    - 設定
        - 名前 : wiki(任意)
        - 有効 : オン (デフォルト)
        - AuthnStatement を含める : オン
        - ドキュメントを署名する : オン
        - アサーションを署名する : オン
        - 署名アルゴリズム : RSA_SHA1
        - SAML Signature Key Name : KEY_ID
        - 正規化方式 : EXCLUSIVE
        - POST Binding を強制 : オン
        - Name ID フォーマットを強制 : オン
        - Name ID フォーマット : username
        - ルート URL : https://wiki.example.com/
        - 有効なリダイレクト URI : https://wiki.example.com/*
    - SAML エンドポイントの詳細設定
         - アサーションコンシューマサービスの POST Binding URL : https://wiki.example.com/
         - アサーションコンシューマサービスの Redirect Binding URL : https://wiki.examle.com/passport/saml/callback
         - ログアウトサービスのRedirect Binding URL : https://wiki.examle.com/passport/saml/callback    
<font color="gray">※設定項目多く画像を小さくしました。画像を別リンクで開いてご覧ください。</font><br clear="left">
<img src="https://qiita-image-store.s3.amazonaws.com/0/291673/c3d6fa33-6b96-3657-4acc-b49cb8e561a0.png" alt="image.png" width="100" height="250"> 
8. Keycloakにおいて、クライアントマッパーの設定をする。   
※プロパティ,Friendly Name,SAML Attribute Nameは下記、同じ値。マッパータイプはUser Property。
    - 右端にある[作成]ボタンから以下を追加
        - lastname
        - id
        - firstname
        - email
        - username
![image.png](https://qiita-image-store.s3.amazonaws.com/0/291673/40be3a85-1fe3-4bbc-59f4-72427f3e86fb.png)


## Growi
- セキュリティ設定
    - SAML 設定
        - エントリーポイント: https://keycloak.examle.com/auth/realms/wiki/protocol/saml
            - https://keycloak.example.com/auth/realms/wiki/protocol/saml/descriptor を参照の上、
    `SingleSignOnService`の`Location`URLを記述
        - 発行者: wiki.examle.com
    - Attribute Mapping
        - Identifier: id
        - Username: username
            - 新規ログイン時、username が一致したローカルアカウントが存在した場合は自動的に紐付ける: レ
        - Mail: email
        - 姓: firstName
        - 名: lastName
    - Options
        - Certificate: https://keycloak.example.com/auth/realms/wiki/protocol/saml/descriptor を参照の上、
    の`dsig:X509Certificate`の内容を記述 (※右端までコピーすること)
<br clear="left">
<img src="https://qiita-image-store.s3.amazonaws.com/0/291673/3c5af01c-fd60-6d1d-f20a-569ec7d9e084.png" alt="image.png" width="450" height="800">

# ログインテスト
1. growi wiki のログインページにおいて、[OAuth]ボタンを下から上にマウスカーソルでなぞり、[ログイン with SAMLSAML]ボタンを押す。<br clear="left">
<img src="https://qiita-image-store.s3.amazonaws.com/0/291673/aadca16d-7362-b123-530d-d695ece7f22a.png" alt="image.png" width="180" height="260">
- keycloakに遷移されることを確認する。
    - エラーが出る場合はトラブルシュートする。
- keycloakの認証ページにおいて、ログインをする
    - エラーが出る場合はトラブルシュートする。
<br clear="left">
<img src="https://qiita-image-store.s3.amazonaws.com/0/291673/48a64f45-5128-15e6-279b-737c9f5892e6.png" alt="image.png" width="180" height="230">

# 署名アルゴリズムを強化したい向け
2018年10月末現在ハードコードするしかないです。※[Github Issue #615](https://github.com/weseek/growi/issues/615)が実装された際にはそちらで設定が可能な予定

- Keycloak - クライアント - 設定
    - 署名アルゴリズム : RSA_SHA256
- Growi
    - 場所：./src/server/service/passport.js:446
    - 値: `     signatureAlgorithm: 'sha256'`

# SAML認証トラブルシュートにおけるお役立ち情報
- ターミナルログ
    - Keycloak
    - Growi
- SAMLデバッグツール
    - [\[Chrome Extention\]SAML Chrome Panel](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace)
    - [\[Firefox Addon\]
SAML-tracer](https://addons.mozilla.org/ja/firefox/addon/saml-tracer/)
    - [SAML Decoder](https://www.samltool.com/decode.php)
    - https://www.samltool.com/online_tools.php
- Growi
    - 環境変数
        - `DEBUG` を`DEBUG=growi:models:external-account,growi:routes:login-passport,growi:service:PassportService`
のように設定した後、起動すると認証周りのデバッグログが多く出て原因箇所を特定しやすい。 (by yuki@weseek slack)

# SAML認証実装までの変遷
- 今年2018年6月ごろから検証を開始。
- 今年2018年6月ごろには[Growi Wiki](https://growi.org)にはSAMLの機構がなかった。
- Github Issueで上げました。今後のことを考え、英語で[Issue #542](https://github.com/weseek/growi/issues/542)を記述。
    - 2018年9月 SAML認証が実装されましたが、検証したところ、うまく動きませんでした。
    - 状況をGrowi Slackに報告し、不具合と認定されました。
    - 2018年10月初旬にSAML認証の不具合が改善され、かつSAML認証のX.509証明書の機能も実装されました。


# <font color="LightGray">special thanks</font>
- <font color="LightGray">miya</font>
- <font color="LightGray">inductor</font>
- <font color="LightGray">yuki@weseek</font>

※なお今後の予定としては、Azure ADでも認証ができるか遊んでみる予定です。