Auth0 Organizationsという素晴らしい機能を今更ながら紹介する
はじめに
Auth0いいですよね!
認証/認可をほとんどおまかせすることができて、ログインページも作ってくれるし、セッション管理もしてくれる。SPAでも。SDKで簡単にトークンの更新をiframeでよしなにやってくれたりと、かなり神ががっているIDaaSです。
そんなAuth0にOrganizationsという機能が2021年4月にリリースされていました。
最近はReactを触ったり、Kotlinを触ったりと全然別のことばかりしていたので、キャッチアップが遅れてしまったのですが、色々試したりして、辛かったマルチテナントの認証/認可が簡単になる可能性を多大に感じたのでまとめてみました。
ただ、もう少しコレがあれば...!と思う点もあったので、そこも踏まえてご紹介していきます。
※ Auth0をちょっと知っている人向けに書くので、細かい用語の説明は入れません
Auth0 Organizationsとは
Auth0 Organizationsとは、Auth0上にエンドユーザーの組織(Organization)を作成する機能です。
Organizationには、Auth0上のユーザーを追加することができ、Organizationに所属するユーザーに対してそのOrganization内で有効な権限を付与することができます。
このように、Auth0 Organizationsはマルチテナントの認証/認可の際に本領を発揮します。
一人のユーザーが複数のテナントに所属するようなユースケースに対しても、簡単に対応することが可能になります。
Auth0 Organizationsが出る前は...
Auth0 Organizationsが出る前は、マルチテナントの認証/認可を実装するのは複雑で、いくつか手段があり、ユースケースに合わせて選択する必要がありました。
また、Auth0の標準機能だけでマルチテナント認証/認可機構を構築できる訳ではなく、Auth0 Rulesを利用して拡張する必要があったり、アプリケーション側で制御するなどの工夫が必要でした。
↓はAuth0 Organizations以前のマルチテナント関連の参考記事です。
- https://auth0.com/docs/best-practices/multi-tenant-apps-best-practices
- https://auth0.com/blog/using-auth0-for-b2b-multi-and-single-tenant-saas-solutions/
- https://buildersbox.corp-sansan.com/entry/2020/04/22/110000
とはいえ、ユーザーが一つのテナントにしか所属しないシンプルなユースケースであれば、多少の拡張で済むので、そこまで問題にはならなかったと思います。
一方で、NotionやGCPのように、ユーザーが複数のテナントに所属するようなユースケースを実現するのは、かなり骨が折れる拡張作業が必要になります。
特に、RBACのような認可の仕組みを入れようとすると、Auth0単体だとかなり難しくなってきます。
過去に、ユーザーが複数のテナントに所属し、かつ、複数のプロダクトを利用するユースケースの認証/認可部分をAuth0を使って構築したことがありますが、正直かなり辛かったです。
Auth0 Organizationsで認証する
さて、ようやく本題に入れます。
ここからは、Auth0 Organizationsを使って実際にマルチテナント認証/認可基盤を構築することで、「Auth0 Organizationsすごいじゃん!」っていうのをお伝えできればと思います。
まずは、認証からです。
ユーザーがOrganizationにログインするまでをDemoアプリを作成して構築します。
1. Organizationの作成
最初にOrganizationを作成しましょう。
サイドバーから、「Organizations」を選択し、「Create Organization」をクリックします。
「Name」と「Display Name」を入力します
「Name」には、小文字アルファベットと数字とアンダースコアのみ使用出来ます。
この「Name」は、ログイン時にユーザーがどのOrganizationにログインするのかの判別に使用します。
次に、作成したOrganizationにコネクションを追加します。
「Connection」タブに移動して「Enable Connections」をクリックします。
今回はとりあえずDatabase
コネクションを追加します。
現時点ではこのOrganizationには誰も所属していないため、このOrganizationにログインできる人は存在しません。
2. ユーザーの追加
ログイン可能なユーザーが一人もいないので、サンプルユーザーを作成して、1.
で作成したOragnizationに追加しましょう。
サイドバーの「User Management > Users」を選択し、「Create User」をクリックします。
では、作成したユーザーをOrganizationに追加します。
1.
で作成したOrganizationに戻り、「Member」タブを移動して「Add Member」をクリックします。
おそらく初期状態では「No users matching search」と出て、選択可能なユーザーが出てこないです。
メールアドレスを入力すると、ユーザーを選択することができるようになります。
3. Applicationの作成
Organizationにログインする準備が整ったので、サンプル用のApplicationを作成しましょう。
デモアプリをReactにする予定なので、 Single Page Application
を選択してください。
「Allowed Callback URLs」に http://localhost:3000
を設定して保存しておいてください。
次に、作成したApplicationのOrganizationタブに移動してください。
初期設定では、「個人ユーザー」のみログイン可能になっていますので、Team members of organizations
に変更してください。
更に「Display Organization Prompt」をONにしてください。
こうすることで、ログイン前に自動的にどのOrganizationにログインするか選択するページに遷移するようになります。
4. デモ用アプリの作成
作成したアプリケーションのQuickStartタブからReactを選択し、サンプルをダウンロードしてください。
ダウンロードが完了したら、sh ./exec.sh
を実行し、http://localhost:3000
にアクセスしてください。
すると、以下のような画面が出るはずです。
この状態で「Log In」ボタンを押すと、以下のような画面が出るはずです。
ここに、1.
で作成したOrganizationの「Name」を入力します。
そうすると、いつものログイン画面が表示されるはずです。
2.
で作成したユーザーでログインすると、ログインに成功するはずです。
ちなみに、このログイン画面はOrganizationごとにカスタマイズすることが可能です。
まとめ
以上で、Auth0 Organizationsを使って認証をすることが出来ました。
今回は1 Organization, 1 Userしか作成しなかったので分かりづらかったですが、Organizationを複数作成するとOrganizationsの強みがハッキリ見えてくると思います。
Organizationsを使わない場合との差異は、大きく以下の2点です
- UserをOrganizationに追加する必要がある
- ログイン前にOrganizationのNameをユーザーに入力してもらう必要がある
Organization Nameの入力に関しては、3.
で設定した「Display Organization Prompt」をOFFにすると入力画面は出ません。
この場合、認証時のパラメーターにorg_id
というキーでOrganizationのIDを渡す必要があります (Organization Nameとは異なりAuth0側で自動に割り振られるIDです)。
テナント毎にサーバーが別れている場合や、メールアドレスなどでorg_id
が認証前に特定できるのであれば、「Display Organization Prompt」をOFFにして、ユーザーの入力を減らしてあげるとユーザーフレンドリーになりそうです。
「Display Organization Prompt」をONにしている場合は、入力するステップが増えるので、ユーザー体験的には微妙だと感じました (特にUserが1つのOrganizationにしか所属していないとき)。
この問題に関しては、Auth0 Actionsを使うことで、Organization Nameの入力をスキップしつつ、デフォルトのOrganizationでログインさせることができたので、別の記事でご紹介しようと思います。
Auth0 Organizationsで認可してみる
ここからより実践に近い認可をOrganizationで試してみます。
認可の手法にはRBAC(Role Base Access Control)を使用します。
0. ユースケース
React.jsのようなSPAではAPIサーバーを持っていることが多いと思います。
Auth0を使われているのであれば、Access TokenをAuth0から取得し、Authorizationヘッダーにsetして、APIサーバーで確認させるような構成になると思います。
マルチテナントのシステムを構築する前提で、Access Tokenに以下の情報を含めたいと思います。
- テナントID
- ユーザーID
- 権限
以上のユースケースをAuth0 Organizationsを使って構築してみましょう。
1. APIを作成する
Auth0でAccess Tokenを作成するためには、APIというエンティティを作成する必要があります。
Auth0ダッシュボードに戻り、サイドバーから「Applications > APIs」を選択し、「Create API」をクリックします。
適当な「Name」と「Identifier」を設定します。
「Identifier」はAccess Token取得時にaudience
として指定する識別子になります。
「RBAC Setting」はどちらもEnableにしましょう。
こうすることで、Access TokenにRoleに紐づくPermissionが勝手に付与されます。
次に、「Permission」タブに移動して、適当はPermissionをいくつか作成してください。
2. Roleの作成
次に、ロールを作成します。
サイドバーの「User Management > Roles」を選択し、「Create Role」をクリックし、適当なロールを作成します。
作成したロールに1.
で作成したPermissionを割り当ててください。
3. OrganizationのUserにRoleをAssignする
最後に、OrganizationのUser2.
で作成したRoleをAssignします。
ここでAssignするRoleはこのOrganizationでログインした時のみ有効になります。
前節の1.
で作成したOrganizationを選択し、「Member」タブに移動し、追加されているユーザーをクリックします。
すると、ユーザー詳細ページの右上に「Assign Roles」ボタンが現れるので、そいつをクリックして2.
で作成したロールをAssignします。
これで準備は完了です。
4. Access Tokenを取得する
デモアプリに戻り、src/auth_config.json
のaudience
を1.
で作成したAPIのIdentifier
に書き換えて、sh exec.sh
を再実行してください。
再度ログインし、ヘッダーから「External API」ページを開いて、「Ping API」をクリックします。
この時、ブラウザのDeveloper Toolsで「Network」タブを開いて通信を除いてみると、http://localhost:3001
にAPIリクエストが送られているはずです。
このリクエストのAuthorization
ヘッダーを見てみると、JWTが入っているはずです。
このJWTをjwt.ioで確認すると、中にsub
とorg_id
とpermissions
というClaimが含まれているはずです。
まとめ
以上で、Organizationを使って認可を実現することができました。
認証と同じく、Organizationを複数作成して、ユーザーを複数のOrganizationに所属させるようにしたときに、Auth0 Organizationsの強みが見えてくると思います。
Auth0 Organizationsが出る以前は、ユーザーがログインするテナントに合わせてロールを取得しパーミッションをAccess Tokenに付与するAuth0 Rulesを作成することは可能でしたが、Auth0 APIsの仕組みを活用できていませんでした。
一方で、Auth0 Organizationsを使うとAuth0 Rulesなどを使って拡張せずとも、Auth0 APIsのRBAC機能を使ってAccess TokenにPermissionを付与することが可能になります。
総まとめ
Auth0 Organizationsを使ってマルチテナント認証/認可を試してみました。
メリデメをまとめてみます。
メリット
- ユーザーが複数テナントに所属するマルチテナント認証・認可を簡単に構築できる
- RBACを使った認可であれば、Ruleは不要
- app_metadataで、ユーザーがどのテナントに所属しているか管理する必要がなくなる
- テナントIDをAccess Tokenに追加するRuleも不要になる
- Organizationに対してMetadataを設定することができる
- IPアドレス制限など、テナント全体に有効化したRuleがある場合にとても強い
これまで触れてきませんでしたが、実はOrganizationに対してMedatada
を設定することができます。
このMedatada
はAuth0 ActionsやRulesから参照することが可能なので、Organizationのユーザー全体に対して何か有効にしたいようなユースケースでは多大な力を発揮します。
デメリット
- ユーザーがログインする時の入力が増えてしまう
- OFFにできる
- 回避方法あり (別記事で紹介します)
- Planによって作成できるOrganization数に上限がある
- Free: -
- Essentials: 50個
- Professional: 100個
- Enterprice: 制限なし
Organizationの作成上限についてはこれまで触れてきませんでしたが、テナント数が多いサービスにおいては大きな制約になりそうです。
Free PlanではAuth0 Organizationsが使えなさそうな表記がされているのですが、一応2021年11月段階では使えています。
とはいえ、そのうち使えなくなる可能性があるので、本番利用する際は少なくともEssentials以上にあげてあげたほうが良さそうです。
総じて、個人的にはマルチテナントなユースケースにおいては、Planの制限に引っかからないのであれば、積極的にOrganizationsを採用しても良いのではないかと思いました。
ログイン前にOrganization Nameを入力してもらうなど、微妙な点は存在しますが、新しい機能ですし、これからアップグレードされていくと思いますので、今後に期待です!
Discussion
とても参考になりました。
こちらの内容も心待ちにしています。よろしくお願いします。