Skip to content

Authentik(SSO) ​

AuthentikのOIDC(Authorization Code Flow+PKCE)でログインします。MFA、パスワードの規則、アカウントの復旧、ログインの流れはAuthentikで管理し、このアプリはユーザー、全体管理者の判定、ブラウザのsession、監査ログを管理します。Projectの中の権限はこのアプリで設定します。

権限は次の2段で決まります。

段決め方変える場所
ログインできるか・全体管理者かAuthentikのgroupと、API serverの環境変数の対応表Authentikのgroupの所属と.env
ProjectのRole(Viewer/Editor/Admin)人への直接付与と、groupへの付与のうち強い方。PublicのProjectでは、ログインできる全員がEditor[プロジェクト設定]

1. Authentikに登録する ​

AuthentikでApplicationとOAuth2/OpenID Providerを作ります。下のhttps://tracking.example.comは、このアプリの実際のHTTPSのURL(MMT_PUBLIC_URL)に置き換えてください。

  1. Authentikの管理画面で[Applications]→[Providers]→[Create]を選び、[OAuth2/OpenID Provider]を作ります。
  2. 次の値を設定します。
項目値
Client typeConfidential
Redirect URIshttps://tracking.example.com/api/auth/callback(完全一致)
Scopesopenid、profile、email、offline_accessの各mapping
Back-channel logout URIhttps://tracking.example.com/api/auth/oidc/backchannel-logout
  1. [Applications]→[Create]でApplicationを作り、上のProviderを選びます。slugは例としてml-trackingにします。
  2. ProviderのClient IDとClient Secretを控えます。Client SecretはAPI serverの.envにだけ置きます。

IssuerのURLはApplication単位で、slugがml-trackingならhttps://sso.example.com/application/o/ml-tracking/です。

scopeとgroups ​

ID tokenとUserInfoの両方に、次のclaimが必要です。

  • emailとemail_verified(email_verifiedがtrueでないログインは拒否します)
  • name(表示名)
  • groups(group名の配列)

UserInfoにgroupsが無いと、ログイン後の再確認で「どのgroupにも入っていない」と判定され、全員のsessionが切れます。Providerのscope mappingでgroupsが出ていることを確かめてください。

offline_access(Authentik標準の「authentik default OAuth Mapping: OpenID 'offline_access'」)は、refresh tokenを発行させるために入れます。入れなくても動きますが、Authentikのaccess tokenの期限(Providerの[Access token validity]。既定は5分)が切れるたびに、ログインし直しが必要になります。

7日保持するには、Providerを編集し、[Advanced protocol settings]の[Scopes]に上のmappingを追加します。[Refresh Token Validity]はdays=7以上にします。既にdays=30なら変更不要です。[Access Token Validity]はminutes=5のままで更新できます。

2. API serverを設定する ​

API serverの.envに次を入れます。本番ではHTTPSが必須です。導入中はローカルの管理者を緊急用に残すため、hybridにします(認証方式の「SSOへ移行する」)。

dotenv
NODE_ENV=production
AUTH_MODE=hybrid
AUTH_SESSION_IDLE_SECONDS=604800
AUTH_SESSION_ABSOLUTE_SECONDS=604800
MMT_PUBLIC_URL=https://tracking.example.com
MMT_WEB_ORIGIN=https://tracking.example.com
OIDC_ISSUER_URL=https://sso.example.com/application/o/ml-tracking/
OIDC_CLIENT_ID=<ProviderのClient ID>
OIDC_CLIENT_SECRET=<ProviderのClient Secret>
OIDC_LABEL=Authentik
OIDC_SCOPES=openid profile email offline_access
OIDC_ALLOWED_GROUPS=mmt-users,mmt-admins
OIDC_ROLE_MAPPING_JSON={"mmt-admins":"admin","mmt-users":"user"}
OIDC_DEFAULT_ROLE=user
OIDC_AUTO_LINK_VERIFIED_EMAIL=false
MMT_SESSION_ENCRYPTION_KEY=<下のコマンドで作った値>
OIDC_RECHECK_SECONDS=60
OIDC_TOKEN_SYNC_MAX_AGE_SECONDS=604800

MMT_SESSION_ENCRYPTION_KEYは、sessionに保存するAuthentikのtokenを暗号化する鍵です。ターミナルで作り、.envにだけ書きます。保存先の鍵(MMT_STORAGE_SECRET_KEY)とは別の値にしてください。

sh
openssl rand -base64 32

設定を変えたらAPIを再起動します。各変数の意味は環境変数の「認証とSSO」にまとめています。

上の設定では、操作しない期間を含め、ログインから7日保持します。既存の.envも更新してください。設定例や既定値を変えても、既存の値は自動で変わりません。反映後、一度ログインし直してrefresh tokenを取得します。

ログインを許すgroupと全体管理者のgroup ​

  • OIDC_ALLOWED_GROUPS: ログインを許すgroup(カンマ区切り)。oidcとhybridでは必須で、空ならAPIが起動しません。どのgroupにも入っていない人はログインできず、ユーザーも作られません。
  • OIDC_ROLE_MAPPING_JSON: group→全体のroleの対応表。roleはadmin(全体管理者)とuser(ログインだけ)の2つです。ほかの値はAPIの起動時にエラーになります。設定しなければ、SSOで入る人は誰も全体管理者になりません。
  • OIDC_DEFAULT_ROLE: 対応表のどのgroupにも入っていない、許可された人のrole。既定はuserです。

複数のgroupに入っている人は、強い方(admin)になります。対応表に書いたgroupもOIDC_ALLOWED_GROUPSに入れてください。許可されていないgroupだけの人は、対応表に関係なくログインできません。

Authentikのgroupの例OIDC_ALLOWED_GROUPS対応表のrole結果
mmt-admins含むadminログインでき、全体管理者になる
mmt-users含むuserログインできる。PublicのProjectはEditorとして使える。それ以外の権限は別に付ける
mmt-proj-asr-editorsだけ含まない—ログインできない
mmt-usersとmmt-proj-asr-editorsmmt-usersを含むuserログインでき、mmt-proj-asr-editorsへの付与も効く

確かめる ​

  1. ブラウザでこのアプリを開き、ログイン画面に[Authentik](OIDC_LABELの値)のボタンが出ることを確かめます。
  2. mmt-adminsの人がSSOでログインし、ユーザーメニューの[全体設定]を開いて、サイドバーに「全体管理」の組(プロジェクト、ユーザーなど)が出ることを確かめます。
  3. mmt-usersだけの人がSSOでログインし、ユーザーメニューの[全体設定]を開いて、サイドバーに「全体設定」の組(アカウント、コンピュータ)は出て、「全体管理」の組は出ないことを確かめます。
  4. どちらかのgroupに入っていない人がログインを断られることを確かめます。断られた理由は監査ログの「SSOログインの拒否」(auth.oidc.denied)に残ります(トラブルシューティングの「SSOでログインできない」)。

ログインのたびに同期すること ​

  • 初めてSSOでログインした人のユーザーを作ります。自分で登録する画面はありません。
  • ログインのたびに、全体管理者かどうかと、その人のgroupを同期します。全体管理者の判定を画面から変えても、次のログインでAuthentik側の状態へ戻ります。恒久的に変えるときはAuthentikのgroupを変えます。
  • 表示名とメールアドレスは、ログインのたびにAuthentikの値へ更新します。
  • 同期で有効な全体管理者が0人になる場合は、そのログインを拒否します(last_admin)。
  • 作成・連携と、全体のroleやgroupの変化は監査ログの「SSOのgroupと権限の同期」(auth.oidc.sync)に残ります。

同じメールアドレスのローカルアカウント ​

既定(OIDC_AUTO_LINK_VERIFIED_EMAIL=false)では、同じメールアドレスのローカルアカウントがあっても、SSOのユーザーは別のユーザーになります。trueにすると、次の条件をすべて満たすときだけ、ローカルアカウントへ結び付けます。

  • email_verifiedがtrue
  • メールアドレスが一致する(大文字小文字は区別しません)、まだSSOと結び付いていないローカルアカウントが1人だけ
  • そのローカルアカウントが全体管理者でも、どこかのProjectのAdminでもない

特権を持つローカルアカウントを自動で結び付けないのは、Authentik側のアカウントで管理者を乗っ取れないようにするためです。この場合のログインはprivileged_link_requiredで拒否します。

ログイン中の権限の再確認 ​

Authentikでgroupから外した人の権限を、次のログインを待たずに止める仕組みです。

  • SSOでログインしたsessionは、OIDC_RECHECK_SECONDS(既定60秒)ごとに、AuthentikのUserInfoで現在のgroupを確かめ直します。access tokenが切れていれば、refresh tokenで更新してから確かめます。
  • 許可されたgroupに入ったままなら、groupと全体管理者の判定を更新して続けます。ProjectのRoleは次の要求から変わります。
  • 許可されたgroupから外れていれば、その人のすべてのSSOのsessionを終了し、API tokenも止めます。
  • Authentikがtokenを拒否した(Authentikでログアウトした、ユーザーを無効にした、refresh tokenが失効した)ときは、そのsessionを終了します。
  • Authentikに接続できないときは、503 oidc_unavailableを返し、sessionは残します。確認できない権限では操作させません。Authentikが復旧すれば、同じsessionで続けられます。

ローカルアカウントのsessionとAPI tokenの要求では、Authentikに問い合わせません。

Back-channel logout ​

AuthentikのProviderに[Back-channel logout URI]を登録すると、Authentikでユーザーやsessionを終了した時点で、このアプリのsessionも終了します。記録は監査ログの「SSOからのログアウト」(auth.oidc.backchannel_logout)に残ります。

SSOのユーザーのAPI token ​

API tokenだけを使い続けると、groupの変化に気付けません。そこで、SSOのユーザーのAPI tokenは、最後のgroupの同期(ログインか再確認)からOIDC_TOKEN_SYNC_MAX_AGE_SECONDS(既定7日)までしか使えません。過ぎると401 identity_sync_requiredになります。tokenは失効しないので、ブラウザで一度ログインすれば同じtokenがまた使えます。

workerや自動実行、CIのように長く動くものには、人のtokenではなくService Accountのtokenを使ってください。Service Accountはこの期限の対象外です(API tokenとService Account)。

groupでProjectの権限を付ける ​

人ごとにRoleを付ける代わりに、AuthentikのgroupにProjectのRoleを付けられます。

  1. Authentikで、Projectごとのgroupを作ります(例: mmt-proj-asr-editors)。
  2. 使う人をgroupに入れ、一度SSOでログインしてもらいます。
  3. [プロジェクト設定]を開き、「Authentik group」の[groupを追加]を押します。
  4. group名とRoleを入力して保存します。
項目入力値
group名Authentikのgroup名をそのまま。大文字小文字と空白も含めて完全一致です。例: mmt-proj-asr-editors
RoleViewer、Editor、Adminのどれか

group名の候補には、一度でも誰かのログインで同期されたgroupだけが出ます。まだ誰もログインしていないgroupは、名前を直接入力します。

保存すると、「Members」の一覧にそのgroupの人が「group mmt-proj-asr-editors」の付与元つきで表示されます。これで設定できています。

OIDC_ALLOWED_GROUPSに入れる必要はありません。ただし、そのgroupの人も、許可されたgroupのどれかに入っていないとログインできません。

groupの所属は、ログインと再確認(既定60秒ごと)で同期します。Authentikでgroupに入れた人は、ログイン中でも1分ほどで権限が付きます。外した人は1分ほどで権限が外れます。ブラウザを使わずAPI tokenだけを使っている人は、次の同期までは元のgroupのままです。すぐ止めたいときは、Projectで付与を外すか、tokenを失効させてください。

実効Roleの決まり方は権限とRoleで説明します。