前置き
ZITADALは OpenID Certified の認定を受けており、Certified OpenID Provider Servers and Servicesにリストされてる1つです。その他の候補について興味がある方はこちら(OpenID CertifiedのOPに関するソースやライセンスを調べてみた)の記事もご確認ください。
趣味の範囲で似たような用途ならKeycloakを使うのですが、2023年の初記事なので、Googleで検索してほぼ日本語の情報が見つからなかった物を選択しようと思い、ZITADELを選びました。
記事の内容としてはZITADELの公式サイトにもクイックスタートが載っていますが、下記2点が気になったので、俺俺クイックスタートを記載しようと思います。
- ZITADEL Cloud を使う前提
- クライアント側 はReactを使う前提
俺俺クイックスタートでは、下記のように変更して説明していきます。
変更前 | 変更後 | 理由 |
---|---|---|
ZITADEL Cloud | Docker compose | 初見では Docker composeのほうがアカウントを作らなくて済むので気楽 |
React | 手動でOAuth2ダンス部分を組立て | 流れるデータがパット見でわかりやすいため ※1 |
※1 ライブラリに依存して実装された処理を後から流れるデータを見たり、ライブラリの実装を見て渡すデータの作り方を確認するよりも、自分で組み立てたほうが理解しやすいと思っています(個人の感想)
What is ZITADEL?
ZITADELは公式のgithubでOSSとしても展開されているのですが、そのREADMEを一部をDeepLなどで意訳をすると下記のようになります
-
Auth0のように素早くセットアップでき、Keycloakのようにオープンソースのユーザー管理をお探しですか?
-
マルチテナントのユーザー管理で、顧客のセルフサービスを必要とするプロジェクトをお持ちですか?
-
ZITADELは、Auth0の簡単さとKeycloakの多用途性を兼ね備えています。
その他に、oryと比較した場合についてですが、関係者同士の議論が面白いので
ぜひ下記の discussions を確認してください。
ZETADELの機能
ZITADELの機能としては Githubページでは下記のようなものが列挙されています。
一部意訳と一部わかりやすく変更して列挙すると下記のようになります。
- シングルサインオン(SSO)
- FIDO2 (Passkeysの対応を含む)
- Username/Passwordでのログイン
- 他要素認証 (OTP, U2F)
- IDの仲介機能
- サーバー間通信への対応 (サービスユーザー)
- パーソナルアクセストークン (PAT)
- 役割ベースのアクセス制御 (RBAC)
- ロール管理の第3者へ委ねる機能
- セルフ登録機能
- セルフサービス機能(エンドユーザー、ビジネスカスタマー、管理者向けなど)
- OpenIDConnect対応
- SAML2対応
- Postgres (version >= 14) または CockroachDB (version >= 22.0) への対応
俺俺クイックスタート
ではさっそく俺俺クイックスタートを開始していきます。
全体の流れとしては下記の流れで作業を行っていきます。
- Docker-composeを起動
- 管理コンソールの起動 及び 管理ユーザーの初期設定
- Organizationの作成
- Userの作成
- Projectの作成
- Applicationの作成
- 認可リクエストの送信
- トークンリクエストの送信
1. Docker compose の起動
公式サイトに docker-compose.yaml が公開されているので、それを取得してみましょう。
また、この docker-compose.yaml はGithubのリポジトリの方でも公開されていますので、適時確認してください。
docker-compose.yaml(クリックで展開)
version: '3.8'
services:
zitadel:
restart: 'always'
networks:
- 'zitadel'
image: 'ghcr.io/zitadel/zitadel:latest'
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --tlsMode disabled'
environment:
- 'ZITADEL_DATABASE_COCKROACH_HOST=crdb'
- 'ZITADEL_EXTERNALSECURE=false'
depends_on:
crdb:
condition: 'service_healthy'
ports:
- '8080:8080'
crdb:
restart: 'always'
networks:
- 'zitadel'
image: 'cockroachdb/cockroach:v22.2.2'
command: 'start-single-node --insecure'
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health?ready=1"]
interval: '10s'
timeout: '30s'
retries: 5
start_period: '20s'
ports:
- '9090:8080'
- '26257:26257'
networks:
zitadel:
取得できたら下記のコマンドで起動してみましょう。
docker compose up --detach
2. 管理コンソールの起動 及び 管理ユーザーの初期設定
起動が完了したら下記のURLでコンソールを開いてみましょう。
-
http://localhost:8080/ui/console
※ 初回起動は少し時間がかかるかもしれません。場合によっては3分ほど放置してみてください。
Loginname としては下記を入力して next を押してください。
- Loginname:
zitadel-admin@zitadel.localhost
その次に下記のようなパスワードの入力画面が出るので、下記を入力して next を押してください。
パスワードを入力すると、下記のような2FAの設定画面が出ます。
今回は一旦 skip を押して飛ばすこととします。
2FAの設定をスキップすると、パスワードの変更画面がでるので、先程のパスワードとともに任意のパスワードを入力して next を押してください。
パスワードは下記の条件があります。
- 8文字以上でなければならない。
- 記号または句読点を含まなければならない。
- 数字を含む必要があります。
- 大文字が含まれている必要があります。
- 小文字を含む必要があります。
今回は下記の値とします。
- Old Password:
Password1!
- New Password: Zit@de1Pass
- Password confirmation: Zit@de1Pass
パスワードを変更すると下記の画面が出るので、管理アカウントが選ばれているまま next を押してください。
パスワード変更後の初期読み込み時に発生しうるエラー
また、この際に下記の画面のような、Organization doesn't exist
のエラーが発生した場合はブラウザの画面を再読み込みしてください。
3. Organization の作成
では次に Organization を作成していきます。
Organization とは、下記の公式の画像のように、UserやProject等のデータを入れることができる、大きな容器のようなものをイメージしてください。
引用: https://zitadel.com/docs/concepts/structure/organizations
では Organization の作成に進みます。まずは先程の ZITADELのAdminのページから、画面最上部の右にあるアイコンを押してください。すると下記のようなトップ画面へ移動します
トップ画面の上部のタブから、 Organizationへ移動します。移動すると下記のような画面になります。
画面上の /ZITADEL のところを押下すると下記の画面のようにメニューが出るので、 New Organization を押してください。
下記のように Organization の名前を選択できる画面が出るので任意のNameを入力して、 Create を押してください。
今回は下記のような名前にします。
- Name: test-org
作成が完了すると下記のように Organization の一覧が表示されます。
作成した Organization 名をクリックすることで、その Organization に移動できるので、押してみましょう。
4. Userの作成
では次に Organization に所属する User を作成していきます。
次は User のタブを押してください。
画面右上の + New を押して下記のようなユーザーの作成画面に移動します。
今回は下記の様な情報を入力していきます。
- Email: test@example.com
- User Name: test@example.com
- First Name: taro
- Last Name: test
- Email Verified: チェック
- Set Initial Password: チェック
- Password: Zit@de1Pass
- Confirm Password: Zit@de1Pass
※ Emailの検証をスキップするために今回は Email Verified と Set Initial Password のどちらにもチェックを入れています。両方にチェックが入っていない場合はメールをチェックします。
ユーザー作成時に発生しうるエラー
User Name は任意の値で問題ありませんが、@
を含んでいない場合は下記のエラーが発生しますので、一旦@
を含んだものを設定してください。
適切な情報を入力して Create を押すと下記のような画面になり、ユーザーの作成は完了します。
5. Projectの作成
では次に Project を作成していきます。
Project のタブを押してください。
下記のような Projectの一覧が表示される画面に移動しますので、 Create New Project を押してください。
プロジェクト名を決める事ができる画面が表示されるので任意の名前を設定してください。
今回は下記の様なNameを入力して、 Continue を押してください。
- Name: test-project
6. Applicationの作成
最後に Application を作っていきます。
先程のプロジェクトの作成完了時の画面の中央の APPLICATIONS の下の +
を押してください。
下記のような画面が表示されるので、 Application 名を設定してください。
Typeは今回はデフォルトのWEBのまま、進めてみます。
また今回は下記のようなNameを入力して、 Continue を押してください。
- Name: test-app
次に下記の画面のように、アプリケーションの設定のデフォルトのセットのようなものの一覧がでますが、今回はデフォルトで選択されている PKCE のまま Continue を押して進めていきます。
次に下記の画面のように Redirect URIs などの設定画面が表示されるので、任意の Redirect URI を設定してください。
今回は下記のような Redirect URI を入力して、 Continue を押してください。
- Redirect URIs: http://localhost:9000/test1
下記のような確認画面が出るので、入力内容を確認して Create を押します。
ClientIdが表示されるのでメモして、 Close を押してください。
今回の例では下記の値になります (※ この値は環境によって変わるため適時書き換えてください)
- ClientId: 197938363217543171@test-project
下記の画面になるので、認可エンドポイントを確認するために、画面右のリストの中の Urls を押してください。
7. 認可リクエストの送信
では認可リクエストを送信してみましょう。
今回はアプリケーションにPKCEの設定を行っているので、認可リクエストに PKCE に関連するパラメータとして、code_challenge と code_challenge_method を載せてリクエストを送信してみます。
PKCEについての解説や、なぜPKCEが必要なのかの詳細が気になる方は下記の記事も参考にしてください。
code_challengeの値は、RFC7636によると code verifier は下記の条件を満たすものです。
code-verifier = 43*128unreserved
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
ALPHA = %x41-5A / %x61-7A
DIGIT = %x30-39
では50文字程度でランダムで作成してみましょう。
openssl rand -base64 50 | tr '/+' '_-' | tr -d '='
上記コマンドを実行すると、今回は下記のような値を取得できました。
x_FOemS-r1ZPTs4QCx9FLBwQwDif1GlJLzc7OE5DuAtsq1boNWNXw83XjkXOnF4LnqE
では次に code challenge を作成します。code challenge を作成するための code challenge method は ZITADELはS256をドキュメントで指示しているので、その指定に従い sha256 とします。RFC 7636どおりに sha256 でハッシュ化した後、base64URL でエンコードを行います。
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
ではさっそく code_challengeを作ってみましょう。
echo -n 'x_FOemS-r1ZPTs4QCx9FLBwQwDif1GlJLzc7OE5DuAtsq1boNWNXw83XjkXOnF4LnqE' | openssl dgst -sha256 -binary | openssl base64 | tr '/+' '_-' | tr -d '='
今回の値では下記のような値になりました。
NWXvPon8IImpDSniZWk8wYuZ6T2jQ6_ADR2Gha5WE8E
下記をブラウザに貼り付けて開いてください。
http://localhost:8080/oauth/v2/authorize?
response_type=code
&scope=openid
&client_id=197938363217543171@test-project
&state=abcdefghijk
&nonce=abcdefghijk
&redirect_uri=http://localhost:9000/test1
&code_challenge=NWXvPon8IImpDSniZWk8wYuZ6T2jQ6_ADR2Gha5WE8E
&code_challenge_method=S256
今回は test taro のアカウントで認証を行いたいので、 Other Userを押してください。
すると下記のような画面がでるので Username を入力して next を押してください。
今回の例では下記のような Username になります。
- Username: test@example.com
Usernameを送信すると下記のようにパスワードを入力する画面がでるので、パスワードを入力し next を押してください。
今回の例では下記のような Password になります。
- Password: Zit@de1Pass
下記のように2FAの設定画面が出ますが、一旦 skip を押して2FAの設定をスキップしてください。
2FAの設定をスキップすると下記の画面のようにパスワードの再設定の画面がでますので、任意のパスワードに再設定して next を押してください。
今回は下記の値とします。
- Old Password:
Zit@de1Pass
- New Password:
Zit@de1Pass2
- Password confirmation:
Zit@de1Pass2
パスワードを変更を終えると、パスワードの変更が完了したことを知らせる下記の画面になるので、 next を押してください。
下記の画面のように自分の設定した Redirect URI に返却されます。
該当の Redirect URI のページを準備していないので、下記の様な画面になりますが、ブラウザのURLさえ見れれば良いので問題ありません。
ブラウザのURLを確認すると下記のような値を取得できます。
8. トークンリクエストの送信
では先程の手順で手に入れた認可コードを使って、トークンリクエストを行ってみます。
PKCE に関連するパラメータとして、code_verifier を載せてリクエストを送信してみます。
任意のターミナルなどで下記を入力してください。
curl -i -X POST \
-H "Content-Type:application/x-www-form-urlencoded" \
-d "client_id=197938363217543171@test-project" \
-d "grant_type=authorization_code" \
-d "code=5_Ou75M0koPPnoSlBBYkewPNXcrzMemPgR1-NLC1ZO3N2g&state=abcdefghijk" \
-d "redirect_uri=http://localhost:9000/test1" \
-d "code_verifier=x_FOemS-r1ZPTs4QCx9FLBwQwDif1GlJLzc7OE5DuAtsq1boNWNXw83XjkXOnF4LnqE" \
'http://localhost:8080/oauth/v2/token'
下記のようにアクセストークンを獲得できるところまでは確認ができました。
HTTP/1.1 200 OK
Cache-Control: no-store
Content-Type: application/json
Expires: Tue, 24 Jan 2023 01:45:48 GMT
Pragma: no-cache
Set-Cookie: zitadel.useragent=MTY3NDUyODM0OHxsYzc0Um5SNVlmcHltZnYxeE54dE1nNnB1bVl5MEpac09mX2ozRk5XNVRTcHg2WnltMFo3VzdYX2Zqelk0QmoxblJzdnhhUUVyRXdSNTdfWWpnaWxCN2RFVlhXdGNxdz18DLFmCO3U0dWntvgacDutqxP009HXJ5UTRqHWaNV7at0=; Path=/; Domain=localhost; Max-Age=31536000; HttpOnly; SameSite=Lax
Vary: Cookie
Date: Tue, 24 Jan 2023 02:45:48 GMT
Content-Length: 1014
{"access_token":"-wu75b2OcHUcjECqCivEBqT7jrGgpndm7ewBHinjnPQrD06V2Ik0NfD6WzX4Zv3uVndCOPE","token_type":"Bearer","expires_in":43199,"id_token":"eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5ODAyNTQyMDM0MjI5NjU3OSJ9.eyJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAiLCJhdWQiOlsiMTk3OTM4MzYzMjE3NTQzMTcxQHRlc3QtcHJvamVjdCIsIjE5NzkzNjc5NTEzNDk4NDE5NSJdLCJhenAiOiIxOTc5MzgzNjMyMTc1NDMxNzFAdGVzdC1wcm9qZWN0Iiwibm9uY2UiOiJhYmNkZWZnaGlqayIsImF0X2hhc2giOiJLOHVORlA0dHo4djdhbFpoOC1ZQy1RIiwiY19oYXNoIjoicGJ0bGlScDVSSHpKeElKaENMeFZxZyIsImFtciI6WyJwYXNzd29yZCIsInB3ZCJdLCJleHAiOjE2NzQ1NzE1NDgsImlhdCI6MTY3NDUyODM0OCwiYXV0aF90aW1lIjoxNjc0NDc4ODI3LCJzdWIiOiIxOTc5MzU5MjA3NzM1OTUxMzkifQ.Mhmlvk4xZOIG-RudIeWUApBPVFT7ShffFXqjkNH4jPFwBjjuckN8eZG-34C4x2cnCmcIcPvcEyMxghsloRHpr_xISXx1cM-gK683Z0jomVOqfRUp8q2U0wjuwnUDXV7HLKRuePwQLSF1HJfaiixbZIpZ74flLDZj8YI_7CawE5ydTTu_psQxe6bqlOKujhO2mVZUdoY4GstlIcV4Xe0VniIje4ahzgk3lZ1ENNBIJqU6kWLugMApSi9i7OHlXfe1TBia6a1VijGilCM94CntzANjnMwJOh5Y2EZdIHhR4YOaii9MA-do2ZqtGyoPN7fs4ItWp_WxkMRhDUBfTTbdoA","state":"abcdefghijk"}
nakamura-kyota@PC-0004168 zitadel-practice
後書き 及び 筆者視点での比較
個人的にはFAPIやCIBAなど比較的新しい技術にも興味があるのですが、Keycloakは対応しているものが多いのですが、ZITADELは進んでいるイメージがあまりありません。
例えば、ハイブリッドフローの対応も進んでいるようには見えておりませんし、CIBAのサポートも今の所予定していないようです。
ZITADELのloadmapを見てもそれらへの対応は進んでいるようには見えないので、比較的最新の技術を使う場合は未だにKeycloakに分があるのではないかと思っています。
ざっくばらんとした記事ですが、新しくZITADELを試そうという方の参考になれば幸いです。