Authagonal

ドキュメント

Authagonal を使い始めるために必要なことはすべてここにあります。最初のテナントの作成から、SSO、SCIM、カスタムブランディングの設定まで扱います。

はじめに

Authagonal は、テナントごとに標準に完全準拠した OIDC サーバーを提供します。各テナントは独自の発行者 URL、ディスカバリードキュメント、トークンエンドポイントを持ち、テナント間で共有されるインフラストラクチャはありません。ゼロから動作するログインフローまで、5 分以内でたどり着けます。

アカウントの作成

authagonal.io でサインアップし、アカウントのスラッグを選択します。スラッグは発行者ドメイン {slug}.authagonal.io になります。アカウントを作成したら、メールアドレスを確認して利用を開始してください。

Authagonal signup page showing tenant slug input and email verification

サインアップ時に、アカウント固有のスラッグを選択します

クライアントの登録

ポータルのサイドバーで クライアント を開き、新しいクライアント をクリックします。アプリケーションの clientId と clientName を入力します。次に、クライアントの URI タブで、リダイレクト URI を少なくとも 1 つ追加します。これは認証後にユーザーが送られる先です。例:https://app.example.com/callback。新しいクライアントではデフォルトでクライアントシークレットが必須のため、バックエンドを持たないブラウザアプリの場合は シークレットを必須にする を 全般 タブでオフにしてください。

New client form with Client ID and Client Name fields

ポータルで新しい OAuth クライアントを登録します

ローカル開発

ローカル開発では、リダイレクト URI に http://localhost:3000/callback を使用してください。Authagonal は、localhost オリジンに対しては HTTPS 以外のリダイレクト URI を許可します。

最初のログイン

最も手早く統合する方法は、JavaScript および TypeScript アプリケーション向けの軽量な OIDC クライアントライブラリ oidc-client-ts を使うことです。

oidc-client-ts integration
import { UserManager } from 'oidc-client-ts';

const mgr = new UserManager({
  authority: 'https://acme.authagonal.io',
  client_id: 'my-app',
  redirect_uri: 'https://app.example.com/callback',
  response_type: 'code',
  scope: 'openid profile email',
});

// Redirect to login
mgr.signinRedirect();

// On callback page
const user = await mgr.signinRedirectCallback();
console.log(user.profile); // { sub, email, name, ... }

ライブラリを使わない最小構成がよければ、標準の OAuth 2.0 認可コードフローを素の fetch で実装できます:

Minimal fetch-based flow
// 1. Redirect the user to the authorization endpoint
const authorizeUrl = new URL('https://acme.authagonal.io/connect/authorize');
authorizeUrl.searchParams.set('client_id', 'my-app');
authorizeUrl.searchParams.set('redirect_uri', 'https://app.example.com/callback');
authorizeUrl.searchParams.set('response_type', 'code');
authorizeUrl.searchParams.set('scope', 'openid profile email');
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
window.location.href = authorizeUrl.toString();

// 2. On the callback page, exchange the code for tokens
const res = await fetch('https://acme.authagonal.io/connect/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type: 'authorization_code',
    code: new URLSearchParams(window.location.search).get('code')!,
    redirect_uri: 'https://app.example.com/callback',
    client_id: 'my-app',
    code_verifier: codeVerifier,
  }),
});

const tokens = await res.json();
// tokens.id_token, tokens.access_token (refresh_token only when offline_access is requested and allowed)
Authagonal login page with email and password fields, branded with tenant logo

テナントのデフォルトのログインページ

サンドボックスモード

まずはサンドボックス環境で統合をテストしてください。サンドボックス環境はポータルの 環境 で作成します。各サンドボックスには専用の URL({env}-{slug}.authagonal.io、例:test1-acme.authagonal.io)があり、ライブユーザーに影響を与えることなく、いつでも空の状態にリセットできます。

ダッシュボード

ポータルのダッシュボードでは、テナントの状況をリアルタイムで把握できます。ユーザー数の推移や認証アクティビティなど最も重要な指標を表示し、ポータルのすべての機能へすばやく移動できます。

概要

ダッシュボードの上部には、ウェルカムメッセージと、テナントのホスト型ログインへの ログインページを開く リンクが表示されます。統計カードの下にある 月間アクティブユーザー メーターはプランの上限に対する使用量を示し、80% を超えるとプランの選択肢へのリンクが表示されます。ページの下部には、サインインのアクティビティ チャートと、最新の監査エントリを表示する 最近のアクティビティ フィードがあります。

Full dashboard view showing the welcome banner, stat cards, monthly active users meter, and sign-in activity chart

統計カードとサインインのアクティビティを表示したダッシュボードのホーム画面

アクティビティ指標

6 つの統計カードで、テナントの状況をひと目で把握できます:

  • アクティブユーザー:テナント内のユーザーの総数
  • サインイン(24時間):過去 24 時間に成功したサインイン
  • MFA 登録済み:MFA に登録済みのユーザーの割合と、登録済みユーザー数および総数
  • 失敗した試行(24時間):過去 24 時間に失敗したサインイン(誤った認証情報、ロックされたアカウント、ポリシーによる拒否など)
  • SCIM 同期:接続された IdP からのプロビジョニングのアクティビティ。「アイドル」または操作件数として表示されます
  • 月額費用:今月これまでの費用と、月末時点の予測額

24 時間のカードは、過去 24 時間をその前の 24 時間と比較します。サインインのアクティビティ チャートは、成功したサインインと失敗したサインインを 1 日ごとに、14、30、90 日 のいずれかの期間でプロットします。ダッシュボードは 1 分ごとに更新されます。

Six stat cards showing active users, sign-ins, MFA enrolment, failed attempts, SCIM sync, and monthly spend

過去 24 時間をまとめた統計カード

クイックナビゲーション

指標の下には、クライアント、SSO、ユーザー、SCIM、ブランディング、設定、請求、ドメイン、監査ログへ直接移動できるナビゲーションカードがあります。各カードには簡単な説明が表示されるため、新しいチームメンバーもすぐに全体を把握できます。

クライアント

OAuth クライアントは、テナントを通じてユーザーを認証するアプリケーションを表します。各クライアントは、リダイレクト URI、スコープ、グラントタイプ、トークンの有効期間、MFA ポリシーについて独自の設定を持ちます。

クライアント一覧

クライアントページには、登録済みのすべてのクライアントが表で表示されます。各行には clientId、表示名、許可されたグラントタイプ(色付きバッジ)、PKCE が有効かどうかが表示されます。行をクリックすると、完全な設定エディターが開きます。

Clients table showing clientId, name, grant type badges, and PKCE status for each registered application

グラントタイプのバッジと PKCE インジケーターを表示したクライアント一覧

クライアントの作成

新しいクライアント をクリックして、新しいアプリケーションを登録します。必要な項目は次の 2 つです:

  • clientId:クライアントの一意の識別子(例:my-spa)
  • clientName:人が読める表示名
New client form with Client ID and Client Name input fields

新しい OAuth クライアントを登録します

クライアントの削除

クライアントを削除するには、クライアント一覧の該当する行にあるゴミ箱アイコンをクリックし、確認のためにクライアント ID を入力します。クライアントは完全に削除され、ユーザーのサインインやトークンのリフレッシュに使用できなくなります。発行済みのアクセストークンは取り消されず、有効期限が切れるまで有効なままです。

クライアント設定リファレンス

各クライアントには、全般、URI、スコープとグラント、トークン、セキュリティの 5 つのタブに整理された包括的な設定オプションがあります。

全般設定

設定説明デフォルト
clientName同意画面とポータルに表示される表示名-
requirePkce認可コードフローで Proof Key for Code Exchange を必須にしますオン
requireClientSecretトークンリクエストにクライアントシークレットを必須にします(SPA などのパブリッククライアントでは無効にします)オン
allowOfflineAccessoffline_access スコープによるリフレッシュトークンの要求をクライアントに許可しますオフ
alwaysIncludeUserClaimsInIdToken対応するスコープが要求されていない場合でも、プロフィール、メール、ロール、グループのクレームを ID トークンに含めますオフ
includeGroupsInTokensgroups スコープが要求されたときに発行されるトークンに、ユーザーの SCIM グループの名前を groups クレームとして含めますオフ

PKCE のセキュリティ

PKCE を無効にすると、認可コードフローのセキュリティが低下します。無効にするのは、PKCE に対応していないレガシークライアントの場合だけにしてください。最新のアプリケーションはすべて、PKCE を有効のままにしておくべきです。

URI

URI フィールドはタグ入力形式です。値を入力して Enter または カンマ を押すと追加されます。タグの X をクリックすると削除されます。

設定説明
redirectUris認証後に許可されるコールバック URL。認可リクエストの redirect_uri パラメーターと完全に一致する必要があります。
postLogoutRedirectUrisログアウト後のリダイレクト先として許可される URL。
allowedCorsOriginsトークンエンドポイントと UserInfo エンドポイントへのクロスオリジンリクエストが許可されるオリジン。
URI configuration section showing tag inputs for redirect URIs, post-logout URIs, and CORS origins

URI を設定するタグ入力フィールド

スコープとグラントタイプ

設定オプション
allowedScopesopenid profile email offline_access phone roles groups
allowedGrantTypesauthorization_code client_credentials refresh_token urn:ietf:params:oauth:grant-type:device_code urn:ietf:params:oauth:grant-type:token-exchange

トークンの有効期間

設定説明デフォルト
accessTokenLifetimeSecondsアクセストークンの有効期間1800(30 分)
identityTokenLifetimeSecondsID トークンの有効期間300(5 分)
authorizationCodeLifetimeSeconds認可コードを交換に使用できる期間300(5 分)
absoluteRefreshTokenLifetimeSecondsアクティビティに関係なく適用される、リフレッシュトークンの最大有効期間2592000(30 日)
slidingRefreshTokenLifetimeSecondsリフレッシュトークンの有効期限は使用するたびにリセットされます(絶対有効期間が上限)1296000(15 日)
Token lifetime configuration fields with numeric inputs for each lifetime setting

クライアントごとにトークンの有効期間を設定します

ログアウト URI

クライアントは、バックチャネルとフロントチャネルの両方のログアウト URI を登録できます。どちらも任意で、片方だけでも両方でも構いません。アプリケーションのセッションの消去方法に合うものを設定してください。

設定説明
backChannelLogoutUri署名付きログアウトトークンを使ったサーバー間の POST。ユーザーのブラウザーがオフラインでも確実に届きます。
frontChannelLogoutUriログアウト時に非表示の iframe 内で表示され、ブラウザーが Cookie とローカルストレージを消去できるようにします。
frontChannelLogoutSessionRequiredオンにすると、ログアウト URL が iss と sid のクエリパラメーターを受け取るため、アプリはログアウトを特定のセッションと関連付けられます。

両方を併用する

バックチャネルはサーバーへの通知を保証し、フロントチャネルはブラウザーを消去します。ほとんどのアプリでは、両方を設定すると効果的です。

MFA ポリシー

各クライアントには独自の MFA ポリシーがあり、クライアントの <strong>セキュリティ</strong> タブで設定します。MFA ポリシーのドロップダウンには、次の 3 つのオプションがあります:

ポリシー動作
無効このクライアントでは MFA を一切求めません
有効ユーザーは任意で MFA に登録できます。登録済みの場合は MFA を求められます
必須このクライアントで認証するには、すべてのユーザーが MFA を完了する必要があります
MFA policy dropdown showing Disabled, Enabled, and Required options on the client configuration page

クライアントごとの MFA ポリシー

エンタープライズ SSO

エンタープライズ SSO を使うと、顧客は自社の ID プロバイダーを持ち込めます。Authagonal は SAML 2.0 と OIDC フェデレーションの両方に対応し、ドメインベースのルーティングにより、ユーザーはメールアドレスに基づいて適切な IdP に自動的に誘導されます。

SSO domain routing flow: shows how email domains are matched to SAML or OIDC identity providers

ドメインベースの SSO ルーティング

SAML 2.0 接続

SAML 接続を作成するには、SSO ページに移動して SAML タブを選択し、次の項目を入力します:

フィールド説明
connectionNameこの接続の、人が読める名前(例:「Acme Corp Okta」)
entityIdSP のエンティティ ID。この値をそのまま、IdP 側でアプリケーションの識別子(エンティティ ID)として登録してください。アサーションでは、この値が Audience として指定されている必要があります
metadataLocationIdP の SAML メタデータ XML ドキュメントの URL
metadataXml貼り付けた IdP メタデータ XML。メタデータ URL を持たない IdP(Google Workspace)や、URL にインターネットから到達できない IdP 向けです。これと metadataLocation のどちらか一方を指定し、両方は指定しないでください
nameIdFormatIdP に要求する NameID フォーマット(任意)。省略すると emailAddress がデフォルトになります。「none」を指定すると NameIDPolicy 自体を省略します(ADFS で推奨)
allowedDomainsこの接続にルーティングされるメールドメイン(例:acme.com)。API で設定します。ポータルでは、接続カードと「ドメインルーティング」タブに表示されます

接続を保存すると、Authagonal はメタデータドキュメントを取得し、IdP の署名証明書、SSO エンドポイント URL、名前識別子のフォーマットをインポートします。メタデータは定期的に更新され、証明書のローテーションが反映されます。

SAML connection creation form with fields for connection name, SP entity ID, and IdP metadata

SAML 2.0 SSO 接続を作成します

OIDC 接続

OIDC フェデレーション接続を作成するには、OIDC タブを選択し、次の項目を入力します:

フィールド説明
connectionNameこの接続の、人が読める名前
metadataLocationOpenID Connect のディスカバリー URL(例:https://login.microsoftonline.com/{tenant}/v2.0/.well-known/openid-configuration)
clientIdこのフェデレーション用に外部 IdP に登録されたクライアント ID
clientSecret外部 IdP の登録に対応するクライアントシークレット
allowedDomainsこの接続にルーティングされるメールドメイン(例:acme.com)。API で設定します。ポータルでは、接続カードと「ドメインルーティング」タブに表示されます
OIDC connection creation form with fields for connection name, discovery URL, client ID, and client secret

OIDC フェデレーション接続を作成します

ドメインルーティング

ドメインルーティングは、メールアドレスのドメインに基づいて、ユーザーを適切な ID プロバイダーへ自動的にリダイレクトします。ユーザーがログインページでメールアドレスを入力すると、Authagonal はドメイン部分(例:acme.com)がいずれかの SSO 接続の allowedDomains と一致するかを確認します。一致した場合、ユーザーは所属組織の IdP にシームレスにリダイレクトされます。

メールドメインSSO プロバイダープロトコル
acme.comAcme Corp OktaSAML 2.0
contoso.comContoso Azure ADOIDC
example.orgExample OneLoginSAML 2.0
Domain routing table showing email domains mapped to SSO connections with protocol type

ドメインルーティングは、メールドメインを ID プロバイダーに対応付けます

SP 起点フロー

デフォルトは SP 起点フローです。ユーザーはあなたのログインページから開始し、適切な IdP に自動的にルーティングされます。/saml/{connectionId}/login または /oidc/{connectionId}/login を使って、特定の接続へユーザーを直接ディープリンクすることもできます。

JIT プロビジョニング

ユーザーが初めて SSO でサインインし、テナントにまだ存在しない場合、Authagonal はアカウントを自動的に作成できます(ジャストインタイムプロビジョニング)。JIT プロビジョニングはデフォルトでオフです。接続の作成時に JIT プロビジョニングを有効にする をオンにすることで、接続ごとに有効化できます。

JIT プロビジョニングが無効な場合、その接続でサインインできるのは、SCIM、ポータルのユーザーページ、または API によって事前にプロビジョニングされたユーザーだけです。不明なユーザーには access_denied エラーが返され、管理者に問い合わせるよう案内されます。

接続ごとの設定

JIT プロビジョニングはテナント全体ではなく、SSO 接続ごとに制御されます。JIT を許可する接続(例:自社でユーザーを管理するパートナー組織向け)と、事前プロビジョニングを必須とする接続(例:SCIM 同期を使うエンタープライズ顧客向け)を併用できます。

展開前にテストする

本番ユーザーに展開する前に、サンドボックスモードで SSO 接続をテストしてください。ライブの認証フローに影響を与えることなく、IdP の設定、属性マッピング、ドメインルーティングを検証できます。

組織スコープの接続

接続は、テナント全体ではなく、テナント内の 1 つの 組織 に属させることもできます。そうした接続が提示されるのは、その組織がすでに特定されている場合だけです。特定の方法は、その組織に紐付けられたカスタムドメイン、サインインリンクの organization パラメーター、またはその 1 つの組織に登録されたクライアントのいずれかで、テナント全体のログインページで提示されることはありません。これらのうちどれが優先されるかは、この順序(先に挙げたものが最優先)で判定されます。

サインインでメンバーシップが作成される

組織スコープの接続を通じてサインインしたユーザーは、JIT プロビジョニングでアカウントが作成されるのと同じように、自動的にその組織のメンバーになります。別途招待する手順はありません。

ドメインの一意性はスコープごと

メールドメインは、テナント全体で 1 回登録でき、さらにそれとは独立して、各組織内でもう 1 回ずつ登録できます。たとえば acme.com は、テナント全体の接続にルーティングすると同時に、組織がすでに選択されている場合はその組織独自の接続にもルーティングできます。できないのは、同じスコープ内の 2 つの接続に属することです。その場合、Authagonal は接続の保存時に拒否します。

ユーザー

ユーザーページでは、テナント内のすべてのエンドユーザーを管理できます。ユーザーの検索、詳細の確認、新しいユーザーの招待ができ、各ユーザーがどのようにプロビジョニングされたかも確認できます。

検索バーは、ユーザー ID またはメールアドレスの完全一致、あるいはメールアドレス、名、姓の前方一致で検索します。また、「すべて」「有効」「無効」のフィルターでステータスごとに一覧を絞り込めます。検索には 300ms のデバウンスがかかっているため、API に過度な負荷をかけずに、入力に合わせて結果が更新されます。結果は 1 ページあたり 50 ユーザーずつ表示されます。ページ間の移動には、表の下部にあるナビゲーションを使用します。

ユーザーテーブル

ユーザーテーブルには、各ユーザーについて次の列が表示されます:

列説明
ユーザーユーザーの名前(名前が設定されていない場合はメールアドレス)。その下にメールアドレスが表示され、メールアドレスが確認されるまで「未確認」バッジが付きます
ステータスActive または Inactive :アカウントが有効かどうかを示します
作成元SCIM または Local :ユーザーの作成方法
ロールユーザーに割り当てられたロール
MFAEnabled :多要素認証に登録済みの場合に表示されます。未登録の場合はダッシュ(-)が表示されます
作成日ユーザーアカウントが作成された日付
User list table with columns for user, status, source, roles, MFA, and created date

検索バーとページ分割を備えたユーザー一覧

ユーザーの招待

ユーザーを招待 をクリックして、テナントにユーザーを招待します。招待されたユーザーには、自分でパスワードを設定するためのメールが届きます。フォームの項目は次のとおりです:

フィールド説明
emailユーザーのメールアドレス(テナント内で一意である必要があります)
firstNameユーザーの名
lastNameユーザーの姓
locale優先言語。ユーザーの UI とメールの言語を設定します。任意で、未設定の場合は英語になります。
organizationIdユーザーを追加する組織(任意)と、その組織でのロール。テナントに組織がある場合に表示されます
Invite user form with email, first name, last name, and Language fields

新しいユーザーを招待します

SCIM でプロビジョニングされたユーザー

SCIM で作成されたユーザーには、「作成元」列に「SCIM」バッジが表示されます。作成、更新、無効化といったライフサイクルは、上流の ID プロバイダーによって管理されます。

優先言語

すべてのユーザーには優先言語があり、ホスト型 UI と、Authagonal が送信するトランザクションメール(確認、パスワードリセット、ウェルカムなど)の両方の言語を決定します。ユーザーの招待時に設定でき、ユーザーの詳細ページからいつでも変更できます。優先言語が設定されていない場合、Authagonal は英語を使用します。セレクターでは、サポートされているすべてのロケール(英語、簡体字中国語、ドイツ語、フランス語、スペイン語、ベトナム語、ポルトガル語、日本語、アラビア語、ヒンディー語、アフリカーンス語)を選択できます。

User detail edit form with profile fields including a preferred Language selector

詳細ページでユーザーの優先言語を設定します

ユーザーの詳細

ユーザー一覧の行をクリックすると、その詳細ページが開きます。そこでプロフィールデータの編集、ロールの管理、MFA のリセット、カスタム属性の確認、ユーザーの削除ができます。

User detail page showing profile fields, status, assigned roles, and custom attributes

プロフィール

メールアドレス、名と姓、電話番号、会社、言語、外部 ID を編集し、ユーザーの有効フラグを切り替えます。メールアドレスまたはメール確認済みフラグを変更するには、管理者またはオーナーの権限が必要です。メールアドレスを変更する場合も、テナント内で一意である必要があります。すでに使用されている場合、API は email_already_in_use を返します。

ロール

ロール ページで定義したロールを割り当てたり解除したりします。クライアントが roles スコープを要求した場合、割り当てられたロールは ID トークンとアクセストークンに roles クレームとして出力されます。

多要素認証

ユーザーに登録されているすべての MFA 認証情報(認証アプリ(TOTP)、WebAuthn/パスキー、リカバリーコード)を、それぞれの登録日時と最終使用日時とともに確認できます。個々の認証情報を削除することも、MFA をすべてリセットすることもできます。どちらも管理者またはオーナーの権限が必要です。リセットすると、ユーザーは次回ログイン時に再登録が必要になります。

カスタム属性

ユーザーに付加される任意のキーと値のデータです。キーは一意である必要があります。属性はユーザープロフィール API と SCIM を通じて公開され、カスタムスコープの userClaims を設定することで、アクセストークンのクレームにマッピングできます。

組織

このユーザーが所属する組織です。これはお客様独自の自由記述の識別子で、ユーザーのトークンと /connect/userinfo に org_id クレームとして出力されます(profile スコープの場合)。Authagonal がこの値を推測して設定することはありません。値を設定するのは、プロビジョニングアプリ、ユーザーを作成した SCIM 認証情報、またはこの画面での手動入力です。

フィールドの横にあるリンクから、同じ値を持つ全員を一覧表示できます。同じ絞り込みは API でも GET /api/v1/users?organizationId= として利用できます。ディレクトリ全体をページ送りせずに、特定の顧客に誰が所属しているかを確認できます。

ユーザーの削除

ユーザーとそのすべての MFA 認証情報を完全に削除します。確認のためユーザーのメールアドレスを入力してください。元に戻すことはできません。

グループ

グループを使うと、ユーザーを整理し、グループメンバーシップをトークンに含めることができます。グループはポータルで手動作成することも、外部の ID プロバイダーから SCIM で自動的にプロビジョニングすることもできます。

グループ一覧

グループは SCIM ページの「グループ」タブに一覧表示され、次の情報が表示されます:

列説明
グループ名グループの表示名
メンバー現在グループに所属しているユーザー数
作成元SCIM または Manual :グループの作成方法
作成日グループが作成された日付
Groups list table showing group name, member count, source badge, granted roles, and created date

作成元インジケーター付きのグループ一覧

グループの作成

新しいグループ をクリックし、グループの 表示名 を入力します。グループ名はわかりやすく、テナント内で一意にしてください(例:「エンジニアリング」、「請求管理者」、「ベータテスター」)。

グループの詳細とメンバー

グループをクリックすると、詳細ビューが開きます。ここでは現在のメンバー全員を確認し、メンバーシップを管理できます:

  • メンバーを追加:メールアドレスまたは名前でユーザーを検索し、グループに追加します。
  • メンバーを削除:各メンバーの横にある削除ボタンをクリックして確定します。グループを通じて付与されていたロールはすべて取り消されます。
Group detail view showing the member list, a user search to add members, and the roles the group grants

詳細ビューでグループメンバーシップを管理します

トークン内のグループ

クライアントで トークンにグループを含める が有効で、かつ groups スコープが要求された場合、発行されるトークンには、ユーザーのグループの表示名を列挙した groups クレームが含まれます:

groups claim
{
  "sub": "user-123",
  "email": "[email protected]",
  "groups": ["Engineering", "Beta Testers"]
}

クライアントごとに有効化

トークンにグループを含める の設定は、クライアントごとに個別に、クライアントの 全般 タブで行います。クライアントで groups スコープも許可されている必要があります。

ロール

ロールは、アプリケーションでのロールベースのアクセス制御(RBAC)を支えます。Authagonal でロールを定義してユーザーに割り当て、トークンの roles クレームを使って、アプリケーションロジックで認可を適用します。

ロールの管理

ロールページには、定義済みのすべてのロールが表で表示され、その場で編集できます。各ロールには次の項目があります:

列説明
名前ロールの一意の識別子(例:「admin」、「editor」、「viewer」)
説明ロールが付与する内容の、人が読める説明
作成日ロールが作成された日付

ロールの作成

新しいロール をクリックし、名前と説明を入力します。ロール名は簡潔にし、アプリケーション全体で一貫した命名規則に従ってください(例:小文字とハイフン:billing-admin)。

インライン編集

ロールは表の中で直接編集できます。ロールの鉛筆アイコンをクリックすると編集モードになり、名前と説明のフィールドが編集可能になります。値を変更したら、チェックマークアイコンをクリックして保存します。変更は直ちに反映されます。

ロールの削除

ロールの削除アイコンをクリックすると、そのロールを削除できます。ロールが完全に削除される前に確認を求められます。ロールを削除しても、既存のトークンがさかのぼって無効になることはありません。削除後に発行される新しいトークンには、そのロールが含まれなくなります。

Roles table with inline editing active, showing editable name and description fields with save and cancel icons

ロール表でのロールのインライン編集

トークン内のロール

クライアントが roles スコープを要求した場合、ユーザーに割り当てられたロールは ID トークンとアクセストークンに roles クレームとして含まれます。アプリケーションはこのクレームを読み取って、認可の判断を行えます:

roles claim in ID token
{
  "sub": "user-123",
  "email": "[email protected]",
  "roles": ["admin", "billing-admin"]
}

SCIM プロビジョニング

SCIM 2.0(System for Cross-domain Identity Management)を使うと、Okta、Azure AD、OneLogin、JumpCloud などのエンタープライズ ID プロバイダーから、ユーザーとグループを自動的にプロビジョニングできます。設定すると、ユーザーアカウントとグループメンバーシップが、上流の IdP から Authagonal テナントへ自動的に同期されます。

SCIM provisioning flow: shows user lifecycle events flowing from enterprise IdP through Authagonal SCIM API to your app via TCC webhooks

下流へのプロビジョニングを伴う SCIM ユーザーライフサイクル同期

セットアップ手順

クライアントで SCIM プロビジョニングを有効にするには、次の手順に従います:

  1. クライアントアプリケーションを選択する:SCIM プロビジョニングを関連付ける OAuth クライアントを選択します。
  2. SCIM トークンを生成する:説明と有効期間(日数)を入力し、トークンを生成します。
  3. トークンをすぐにコピーする:トークンの生の値は一度しか表示されません。ダイアログを閉じる前にコピーしてください。
  4. IdP を設定する:ID プロバイダーの SCIM 設定で、ベース URL とベアラートークンを入力します。
  5. ユーザー同期をテストする:IdP からテスト同期を実行し、Authagonal ポータルにユーザーが表示されることを確認します。

SCIM ベース URL

ID プロバイダーに次のベース URL を設定します:

SCIM Base URL
https://{slug}.authagonal.io/scim/v2

{slug} をテナントのスラッグに置き換えてください。

SCIM configuration page showing client selector, token generation form, and base URL

トークン生成を備えた SCIM セットアップページ

トークンの管理

SCIM トークンは、IdP からのプロビジョニングリクエストを認証します。クライアントごとに複数のトークンを管理できます:

フィールド説明
説明トークンを識別するためのラベル(例:「Okta Production SCIM」)
有効期間トークンの有効期間(日数、1 から 3650、デフォルトは 365)。
ステータスアクティブなトークンは使用中です。取り消されたトークンには Revoked バッジが表示され、リクエストを認証できなくなります。

トークンを取り消すには、その横にある 取り消す ボタンをクリックします。取り消されたトークンは監査のために一覧に表示されたままになりますが、直ちにリクエストを受け付けなくなります。

SCIM token list showing active and revoked tokens with description, expiry date, and revoke button

アクティブなトークンと取り消されたトークンのインジケーターを備えたトークン管理

トークンをすぐにコピーする

SCIM トークンの生の値は、作成時に一度だけ表示されます。すぐにコピーしてください。後から取得することはできません。トークンを紛失した場合は、新しいトークンを生成し、IdP の設定を更新する必要があります。

接続のテスト

ServiceProviderConfig エンドポイントにクエリを送信して、SCIM 統合が機能していることを確認します:

Test SCIM connectivity
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://acme.authagonal.io/scim/v2/ServiceProviderConfig

成功すると、サポートされている SCIM 機能を説明する JSON ドキュメントが返されます。PATCH とフィルタリングはサポートされていますが、一括操作、パスワード変更、並べ替え、ETag はサポートされていません。

優先言語

SCIM の preferredLanguage 属性(ない場合は locale)は、ユーザーに保存される言語にマッピングされます。SCIM でプロビジョニングされた SSO ユーザーには、IdP から送られた言語でローカライズされたメールが自動的に届きます。

認証情報から見える範囲

SCIM 認証情報から見えるのは、その認証情報がプロビジョニングしたユーザーとグループだけです。別のコネクターが作成したユーザーの読み取り、更新、削除には 404 が返され、一覧には自分のものだけが返されます。また、グループのメンバーシップに指定できるのは、同じコネクターがプロビジョニングしたユーザーだけです。それ以外の方法(管理者、セルフサービスのサインアップ、SSO のジャストインタイムプロビジョニング)で作成されたアカウントは、SCIM からは一切見えません。

この境界はトークンごとではなく、クライアントごとです。同じクライアントに対して発行された 2 つの認証情報は、シークレットが 2 つある 1 つの ID であり、どちらももう一方が作成したものを変更できます。互いに信頼できないコネクターには、それぞれ別のクライアントを割り当ててください。externalId も同じ範囲で区切られるため、2 つのコネクターがそれぞれ別の人物に ext-001 を使っても衝突しません。

プロビジョニング解除

DELETE /scim/v2/Users/{id} はアカウントを無効化し、削除済みとしてマークします。レコードは RFC 7644 が認めるとおり保持されますが、以降のすべての操作に 404 を返し、一覧からも除外されます。MFA の登録とグループメンバーシップは消去され、externalId のマッピングは解放され、発行済みのトークンはすべて失効するため、アクセスは次のトークン有効期限を待たずに直ちに終了します。

同じ人物が後で再雇用されて再作成された場合、その人には新しいユーザー ID が割り当てられます。識別子が再利用されることはありません。ID はこれまでに発行したすべてのトークンのサブジェクトであるため、再利用すると、それを信頼するすべてのアプリケーションで、新しく加わった人に前の保持者の履歴が知らないうちに引き継がれてしまいます。

同期ユーザーへの組織のタグ付け

SCIM には、コネクターがどの顧客を同期しているかを伝える手段がありません。コアの SCIM には組織属性が定義されていないため、通常のユーザー作成で分かるのはその人の名前とメールアドレスだけで、誰に属しているかは分かりません。複数の顧客があなたのテナントにプロビジョニングすると、各顧客のユーザーは区別できない状態で届きます。

この問題には、リクエストではなく認証情報が答えます。SCIM トークンを作成するときに、組織 でテナントの組織を 1 つ選択します(この選択欄は、テナントに組織があると表示されます)。そのトークンを通じてプロビジョニングされたユーザーはすべてその組織のアクティブなメンバーになり、以降、ユーザーのトークンにはその組織が org_id クレームとして含まれます。同じクライアントに対して顧客ごとに認証情報を 1 つずつ発行すれば、顧客ごとにクライアントを登録しなくても、同期されたユーザーが正しく顧客に紐付けられます。空欄のままにするとユーザーにはタグが付きません。

タグ付けは分離ではない

所有権はトークンごとではなく、クライアントごとに適用されます。同じクライアント上の 2 つの認証情報は、シークレットが 2 つある 1 つの ID です。どちらも、もう一方が作成したユーザーの読み取り、名前の変更、無効化、削除ができます。すべての認証情報を自分で保持している場合は問題ありません。各顧客の IT チームがそれぞれの認証情報を保持する場合は、顧客ごとにクライアントを用意し、その認証情報にも組織を設定してください。

タグはユーザーの作成時に適用され、その後の更新で適用されることはありません。そのため、定期的な差分同期で既存のアカウントが知らないうちに移動することはありません。プロビジョニングアプリも併用している場合は、認証情報に明示的に設定したタグが優先されます。/try レスポンスが組織を埋めるのは、組織がまだ空の場合だけです。

サポートされるスキーマ

コアの SCIM 2.0 の User スキーマと Group スキーマ(RFC 7643)を実装しています。サポートされるユーザー属性は、userName、name.givenName、name.familyName、displayName、emails、active、externalId、preferredLanguage / locale です。

エンタープライズユーザー拡張は実装していないため、department、manager、employeeNumber、costCenter、division、organization は、作成、置換、PATCH のいずれでも、保存されずに受け入れられたうえで無視されます。Entra と Okta はどちらもデフォルトでこれらの一部をマッピングしますが、属性マッピングから削除する必要はありません。ユーザーを顧客のいずれかに紐付けるには、代わりに SCIM 認証情報に組織を設定してください。エンタープライズの organization 属性は顧客の ID プロバイダーが主張する値であり、意図的にユーザーの org_id にはならないようにしています。

OAuth スコープ

スコープを使うと、クライアントはユーザーのデータや権限の特定の部分を要求できます。Authagonal は、標準の OIDC スコープと、API 用に独自に定義するカスタムスコープの両方をサポートします。

組み込みスコープ

スコープ説明
openidすべての OpenID Connect フローで必須です。ID トークンを発行します。
profile標準のプロフィールクレーム(name、given_name、family_name、locale、org_name)を返します。
emailユーザーのメールアドレスと確認状態を返します。
phoneユーザーの電話番号(phone_number)を返します。
offline_accessアクセストークンと併せてリフレッシュトークンを発行します。
rolesユーザーの roles クレームを出力します。このスコープがない場合、ロールは出力されません。
groupsユーザーの groups クレーム(SCIM グループのメンバーシップ)を出力します。このスコープがない場合、グループは出力されません。

カスタムスコープ

スコープページで独自のスコープを定義します。各スコープは、クライアントが要求できる権限またはリソースを表します(例:billing.read、orders.write)。

Custom scope creation form with name, display name, description and User Claims fields
フィールド説明
nameトークンリクエストで送信されるスコープ識別子(例:billing.read)。
displayName同意画面に表示される、人が読める形式のラベル。
description同意画面で表示名の下に表示される、より詳しい説明。
userClaimsこのスコープが付与されたときにアクセストークンと ID トークンに追加されるクレーム。
showInDiscoveryDocumentオンにすると、スコープが /.well-known/openid-configuration に表示されます。
emphasize同意画面でスコープを機密性の高いものとして強調表示します。
required同意時にユーザーがスコープの選択を解除できないようにします。
group同意グループ:見出しを共有するスコープは、同意画面で 1 つのチェックボックスの下にまとめて表示されます。表示上の設定のみです。
allowedRolesこのスコープを付与されるためにユーザーが持っている必要があるロール。空の場合は全員に許可されます。これらのロールのいずれも持たないユーザーは、拒否されるのではなく、トークンからこのスコープが除外されます。

同意との連携

RequireConsent: true のクライアントは、初回のリクエスト時にユーザーに同意を求めます。スコープを削除しても、発行済みのトークンは取り消されません。必要に応じて明示的に取り消してください。

トークンのカスタムクレーム

カスタムクレームは2つの要素から成ります。ソースはユーザーごとのデータです。各 AuthUser には customAttributes ディクショナリがあり、ポータル(ユーザー → 対象ユーザー → カスタム属性)、SCIM、または TCC プロビジョニングフックから値を設定できます。送出はスコープごとです。各スコープの userClaims リストが、サーバー外への送出を許可するキーを指定します。

クライアントがスコープを要求すると、Authagonal は付与されたスコープを順に調べ、それらの userClaims リストの和集合を取り、ユーザーの customAttributes からそのキーだけを出力します。不明なキーは何も通知せずに破棄されるため、クライアントが名前を推測して属性を読み取ることはできません。標準の OIDC クレーム(sub、email、name など)は仕様に従い、このホワイトリストの対象外です。

Example: project-scope claims on an access token
# 1. On the user (Portal → Users → {user} → Custom Attributes)
department = "engineering"
employee_id = "E-1042"
seat_tier = "enterprise"

# 2. On a custom scope (Portal → Scopes → projects.read)
name        = "projects.read"
userClaims  = ["department", "seat_tier"]   # <-- whitelist

# 3. Client requests scope=openid projects.read
# Decoded access token (relevant fields only):
{
  "sub": "u-9b…",
  "scope": "openid projects.read",
  "department": "engineering",
  "seat_tier":  "enterprise"
  // employee_id is NOT emitted; it's not in the whitelist for any granted scope.
}

フェデレーションのクレームはセッション単位で不足分を補う

ユーザーが上流の IdP(SAML/OIDC SSO)経由でサインインした場合、IdP から届くセッション単位のクレーム(例:SAML アサーションからマッピングされた department 属性)は同じスコープのホワイトリストを通過しますが、不足分を補うだけです。キーが重複した場合は、永続化された customAttributes の値が優先されます。これらはこのセッションのトークンに出力され(リフレッシュのローテーション後も維持されます)、ユーザーレコードには書き戻されません。

クライアントへのスコープの割り当て

クライアント → スコープとグラントタブで、許可するスコープを追加します。クライアントは付与されたスコープしか要求できず、不明なスコープは invalid_scope で拒否されます。

ブランディング

テナントのログインページのルック&フィールをカスタマイズします。ブランディング設定を使うと、ロゴやカラーから高度な CSS オーバーライドまで、認証体験を自社製品のビジュアルアイデンティティに合わせられます。

外観

設定説明
appNameログインページのヘッダー(ロゴが設定されていない場合)とトランザクションメールに表示されるアプリケーション名
logoUrlロゴ画像の URL。ログインページの上部に表示されます。推奨サイズ:200x60px または同程度の縦横比。
primaryColorボタン、リンク、フォーカス状態に使われるプライマリのブランドカラー。カラーピッカーまたは 16 進数の入力で設定します。値を変更するとライブプレビューが更新されます。
customCssUrlデフォルトのスタイルの後に読み込まれる CSS ファイルの URL。ログインページと同じオリジンから配信される必要があります。他のオリジンの URL は無視されます。
Branding appearance settings with app name input, logo URL field, color picker with hex input, and custom CSS URL field

カラーのライブプレビュー付きの外観設定

連絡先情報

設定説明
supportEmailログインページに表示されるサポート用メールアドレス。ユーザーがアカウントについてサポートを必要とするときに表示されます。

ログインページの表示切り替え

テナントのログインページに表示する要素を制御します。

切り替え説明デフォルト
showForgotPasswordログインフォームに「パスワードをお忘れですか?」リンクを表示オン
showRegistrationセルフサービスのユーザー登録用に「サインアップ」リンクを表示オン
poweredByログインページの下部に「Powered by Authagonal」バッジを表示オン
A customized login page showing a branded logo, custom primary color on the sign-in button, and support email in the footer

カスタムブランディングを適用したログインページの例

カスタム CSS

ログインページの外観を完全に制御するには、ブランディング設定で CSS ファイルの URL を指定します。このファイルはデフォルトのスタイルの後に読み込まれるため、指定したルールが優先されます。URL はログインページと同じオリジンである必要があり、他のオリジンのスタイルシートは読み込まれません。

CSS カスタムプロパティ

ログインページは、よく使うオーバーライド向けに CSS カスタムプロパティ(変数)をサポートしています。CSS ファイルでこれらを設定すれば、複雑なセレクターを書かずにカラー、フォント、形状を変更できます。
/* your-custom-styles.css */
:root {
--auth-bg: #1a1a2e;
--auth-card-bg: #16213e;
--auth-heading: #e0e0e0;
--auth-radius: 12px;
--auth-font: 'Inter', sans-serif;
}
変数説明デフォルト
--auth-bgページの背景色#f3f4f6
--auth-card-bgログインカードの背景white
--auth-heading見出しのテキストカラー#111827
--auth-radiusカードの角の丸み0.5rem
--auth-fontフォントファミリーinherit

ダークモード

ログインアプリには、ライト、ダーク、システムの各テーマが用意されています。ブランディングページの ダークモード 設定でデフォルトを選択します:オフ、自動(システムの設定に従います。これがデフォルトです)、常にダークのいずれかです。ユーザーは引き続きログインページの切り替えで選択でき、その選択はセッションをまたいで保持されます。system に設定すると、SPA は prefers-color-scheme をリアルタイムに追従します。

ライトの値は :root で宣言され、ダークのオーバーライドは .dark にスコープされます。customCssUrl で設定したテナントのブランディングが常に優先されるため、ユーザーのテーマにかかわらずカラーは維持されます。

要素セレクター

より細かく制御するには、data-auth 属性を使って特定の要素を対象にします。これらのセレクターはアップデートをまたいで安定しており、内部のクラス名を変更しても壊れません。
セレクター要素
[data-auth="page"]ページ全体の背景コンテナー
[data-auth="header"]ロゴとアプリ名の領域
[data-auth="logo"]ロゴ画像
[data-auth="app-name"]アプリ名の見出し(ロゴが未設定の場合)
[data-auth="content"]メインコンテンツ領域(フォーム、メッセージ)
[data-auth="login-form"]ログインフォーム要素
[data-auth="email-field"]メール入力欄のラッパー
[data-auth="password-field"]パスワード入力欄のラッパー
[data-auth="submit-button"]サインインボタン
[data-auth="languages"]言語選択バー

設定

テナント全体のセキュリティポリシー、ウェブフック、環境設定を構成します。これらの設定は、クライアント単位で上書きされない限り、すべてのクライアントにグローバルに適用されます。

パスワードポリシー

ユーザー → 設定 で、テナントのすべてのユーザーに適用するパスワードの複雑さの要件を定義します:

設定範囲デフォルト
minPasswordLength6 – 1288
requireUppercaseオン / オフオン
requireLowercaseオン / オフオン
requireDigitオン / オフオン
requireSpecialCharオン / オフオン
Password policy settings showing minimum length slider and toggle switches for character requirements

パスワードポリシーの設定

MFA ポリシー

ユーザー → 設定 で設定するテナント全体の MFA ポリシーは、多要素認証のデフォルトの動作を決めます。個々のクライアントでこの設定を上書きできます。

ポリシー動作
DisabledMFA は利用できません。ユーザーは MFA に登録できません。
EnabledMFA は任意です。ユーザーは登録するかどうかを選択でき、登録済みの場合はログイン時に求められます。
RequiredMFA は必須です。すべてのユーザーが MFA に登録し、ログインのたびに第 2 要素を完了する必要があります。

セッションとロックアウト

セッションの有効期間とアカウントロックアウトの動作を制御します。

設定範囲デフォルト
sessionLifetimeMinutes5 – 43,200(30 日)60
maxFailedAttempts1 – 1005
lockoutDurationMinutes1 – 1,440(24 時間)10
Session and lockout settings with numeric inputs for session lifetime, max failed attempts, and lockout duration

セッションとロックアウトの設定

ウェブフック

ウェブフックを使うと、認証イベントにリアルタイムで対応できます。2 つのイベント(onUserAuthenticated、onTokenIssued)は強制可能です。デフォルトでは非同期に発火してユーザーをブロックしませんが、イベントごとに強制をオプトインでき、その場合は 2xx 以外のレスポンスまたは {"allow": false} の本文でアクションが拒否されます。残りのイベントは通知で、常にファイア・アンド・フォーゲットであり、ブロックすることはありません。

イベント種類説明
onUserAuthenticated強制可能ログインが成功した後に発火します。デフォルトはファイア・アンド・フォーゲットのため、ログインのレイテンシーには影響しません。<code>webhookEnforceUserAuthenticated</code> を切り替えるとブロッキングになり、2xx 以外のレスポンスまたは <code>{"allow": false}</code> の本文でログインが拒否されます。
onTokenIssued強制可能トークンの発行前に発火します(authorization_code、refresh_token、client_credentials)。デフォルトはファイア・アンド・フォーゲットです。<code>webhookEnforceTokenIssued</code> を切り替えるとブロッキングになり、2xx 以外のレスポンスまたは <code>{"allow": false}</code> の本文でトークンの発行が阻止されます。
onUserCreated通知新しいユーザーが登録された、または SCIM でプロビジョニングされたときのファイア・アンド・フォーゲットの通知。
onUserUpdated通知ユーザーレコードが更新されたとき(プロファイルの変更、ロールの変更、SCIM による更新)のファイア・アンド・フォーゲットの通知。
onUserDeleted通知ユーザーが Portal/SCIM 経由または保持ポリシーによって削除されたときのファイア・アンド・フォーゲットの通知。
onLoginFailed通知誤った認証情報、ロックアウト、またはポリシーによる拒否でログインの試行が失敗したときのファイア・アンド・フォーゲットの通知。

その他のウェブフック設定:

設定範囲デフォルト説明
webhookTimeoutSeconds1 – 305強制ウェブフックのレスポンスを待つ最大時間。超えるとタイムアウトします
webhookFailOpenオン / オフオン有効にすると、強制ウェブフックに到達できない場合やタイムアウトした場合でも、操作の続行が許可されます
Webhook configuration section showing URL inputs for each event type, timeout slider, and fail-open toggle

ウェブフックイベントの設定

強制ウェブフックの可用性

強制ウェブフックは認証フローをブロックできます。ウェブフックのエンドポイントがダウンし、webhookFailOpen が無効になっていると、どのユーザーもログインできなくなります。ウェブフックの障害時にブロックすることを義務づける厳格なコンプライアンス要件がない限り、フェイルオープンモードを使用してください。

ウェブフックの検証

いずれかのウェブフック URL が設定されると、Authagonal はテナントごとの署名シークレット(whsec_… の値で、設定 → ウェブフックに読み取り専用で表示されます)を発行します。すべての送信配信には X-Authagonal-Signature: t=<unix>,v1=<hex> ヘッダーが付き、v1 は未加工のリクエスト本文に対して計算した HMAC-SHA256(secret, "{t}.{body}") です。エンドポイント側でこれを再計算して定数時間で比較し、リクエストが本当に Authagonal から送られ、改ざんされていないことを確認してください。また、リプレイを防ぐため、t が古すぎる配信は拒否してください。

ウェブフックの検証(Node.js)
import crypto from 'node:crypto';

// rawBody MUST be the exact bytes Authagonal sent: verify before any JSON re-serialization.
function verifyAuthagonalWebhook(signatureHeader, rawBody, signingSecret) {
  const parts = Object.fromEntries(signatureHeader.split(',').map((p) => p.split('=')));
  const { t, v1 } = parts;

  // Replay protection: reject deliveries older than 5 minutes.
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;

  const expected = crypto
    .createHmac('sha256', signingSecret)
    .update(`${t}.${rawBody}`)
    .digest('hex');

  return v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

署名シークレットのローテーション

署名シークレットの横にある再生成を使ってローテーションします(漏洩が疑われる場合など)。以前のシークレットは即座に無効になるため、検証側を新しい値に更新してください。そうしないと、処理中の配信で署名チェックが失敗し始めます。

メンテナンス時間帯

テナントのデータをストレージシャード間で移動するなど、影響の大きい操作を行うメンテナンス時間帯の希望を設定します。UTC の時(0–23)を選択します。利便性のため、ポータルにはローカルタイムゾーンでの対応する時刻も表示されます。

サインアップとアクセス

誰がテナントのユーザーになれるか、またどのような条件でサインインできるか。

設定デフォルト説明
公開サインアップオン誰でも自分で登録できるかどうか。オフにすると登録ページが非表示になり、登録 API も拒否されます。これは重要です。リンクを隠すだけではエンドポイントが開いたままになるからです。SCIM、API、招待でユーザーを自分でプロビジョニングする場合に使用します。
サインインにメール確認を必須にするオン未確認のアドレスではサインインできません。自社のアプリ側で確認状態を判定する場合はオフにしてください。どちらの場合も email_verified クレームはトークンに含まれるため、その情報は失われません。
動的クライアント登録オフクライアントが RFC 7591 に基づいて実行時に自身を登録できるようにします。これは AI エージェントや MCP コネクターがフローを開始する前に必要なものです。デフォルトはオフで、有効にしても開放されるのは自分のテナントだけです。登録には、設定にかかわらずレート制限、PKCE、同意が常に求められます。
ポータルの MFA ポリシー無効自社チームがポータルにサインインする際の多要素認証。エンドユーザー向けのポリシーとは独立して設定します。無効、ログイン時に提示、必須のいずれかです。
最大ユーザー数なしデフォルトではユーザー総数に上限はなく、上限を設けるプランもありません。テナントオーナーのメールアドレスが未確認の間は、5 ユーザーという一時的な上限が適用されます。メールアドレスが確認されると、この上限は恒久的に解除されます。

非アクティブユーザーの保持

使われなくなったアカウントを任意で無効化し、その後削除できます。これにより、ディレクトリに休眠中の ID がいつまでも溜まることを防げます。どちらも設定しない限りオフで、削除は元に戻せません。

設定デフォルト説明
無効化までの期間(非アクティブ日数)なしこの期間サインインしていないアカウントを無効化します。レコードは保持され、再度有効化できます。
削除までの期間(非アクティブ日数)なしアカウントを完全に削除します。元に戻せないため、オンにする前に下記の警告期間とウェブフックを設定してください。
警告日数7無効化または削除の何日前に警告ウェブフックを発火させるか。介入するための時間を確保できます。
保持ウェブフック-警告と実行されたアクションの送信先。本人に通知したり、アカウントを維持したりできます。

監査エクスポートとリモートバックアップ

要求に応じてではなく、スケジュールに従ってデータを取り出す 2 つの方法です。監査エクスポートは、完了した 1 日分の監査イベントを指定した URL に送信します。送信元が当社であることを検証できるよう署名されており、SIEM やコンプライアンスアーカイブへの取り込みに使えます。リモートバックアップは、日次および週次バックアップのコピーを自分が管理する送信先に送ります。認証なし、Basic 認証、ベアラートークンのいずれかを選べます。監査エクスポートは監査ログページの エクスポート タブで、リモートバックアップは バックアップ ページで構成します。どちらも、当社が保持するバックアップとは独立して、お客様自身が保持するものです。

サンドボックス環境

環境ページでは、サンドボックス環境を管理します。サンドボックス環境は名前付きの分離された環境で、それぞれ独自のユーザー、クライアント、署名鍵、MFA 登録、グラントを持ち、個別の URL でアクセスできます。ブランディング、プラン、請求はライブと共有されます。ライブのユーザーに影響を与えずに、設定変更、SSO 連携、ウェブフックのエンドポイントをテストするのに使用します。デフォルトで最大 5 つまで作成でき、アクティブなサンドボックスユーザーは MAU にカウントされます。

操作説明
環境を追加新しい環境を作成します。名前は 1 から 20 文字の英小文字と数字で、「live」は予約されています。環境は空の状態で始まり、ライブからは何もコピーされません。
リフレッシュ環境のデータを消去し、空の状態にリセットします。
削除サンドボックス環境とそのすべてのデータを完全に削除します。

各環境には {name}-{slug}.authagonal.io でアクセスできます。

Environments page listing sandbox environments with their URLs and Refresh and Delete actions

サンドボックス環境の操作

請求

ポータルの請求ページで、サブスクリプションと請求を管理します。このページでは現在のプランの概要を確認でき、支払い方法、請求書、プラン変更を管理する Stripe の請求ポータルにアクセスできます。

サブスクリプション情報

請求ページには、現在のサブスクリプションの詳細がひと目でわかるように表示されます。サブスクリプションの状態を示すステータスバッジ(active、trialing、past_due、canceled、unpaid)とともに、プラン名、現在の請求期間(開始日と終了日)、そして現在の期間の終了時にサブスクリプションがキャンセルされる設定かどうかが表示されます。

サブスクリプションの管理

サブスクリプションを管理ボタンをクリックすると、Stripe の請求ポータルが新しいウィンドウで開きます。そこで支払い方法の更新、請求書の表示とダウンロード、プランの変更、サブスクリプションのキャンセルができます。

まだサブスクリプションがない場合は、代わりに請求をセットアップの案内が表示され、プランの選択と支払い情報の入力を順に進められます。

Billing page showing subscription status, plan name, billing period, and Manage Subscription button

請求ページには現在のサブスクリプションの詳細が表示され、Stripe にアクセスできます

支払いのセキュリティ

すべての請求処理は Stripe を通じて行われます。お客様の支払い情報が Authagonal のサーバーに保存されることはありません。

カスタムドメイン

認証ページを、デフォルトの {slug}.authagonal.io ではなく独自のドメイン(例:auth.yourdomain.com)から配信します。カスタムドメインにより、ユーザーにシームレスでブランド化された認証体験を提供できます。

ドメインの追加

ドメイン追加フォームに、使用したいホスト名(例:auth.yourdomain.com)を入力します。追加すると、ドメインは pending_verification ステータスでドメイン一覧に表示されます。

DNS による検証

ポータルに表示される、そのドメイン用の 2 つの CNAME レコードを作成します。どちらも {slug}.authagonal.io を指します。1 つはホスト名自体のレコードで、トラフィックを処理し、プロキシ経由にしてもかまいません。もう 1 つは _authagonal-challenge. の後にホスト名を続けた名前のレコードで、所有権を証明するためのものであり、DNS のみ(プロキシなし)にする必要があります。レコードを設定したら、DNS を確認 をクリックして検証します。保留中のドメインは自動的にも再確認されます。

CNAME records
auth.yourdomain.com.                        CNAME  acme.authagonal.io.
_authagonal-challenge.auth.yourdomain.com.  CNAME  acme.authagonal.io.

DNS の反映

DNS の反映には最大 48 時間かかることがあります。検証に失敗した場合は、しばらく待ってから再試行してください。

TLS 証明書

ドメインの検証が完了したら、ユーザーが HTTPS で安全に接続できるよう TLS 証明書が必要です。Authagonal は 2 つの方法をサポートしています。

自動(cert-manager):Authagonal が cert-manager を使って TLS 証明書を自動的にプロビジョニングし、更新します。ほとんどのユーザーにはこの方法をおすすめします。追加の設定は不要です。

持ち込み(BYO):独自の証明書と秘密鍵を PEM 形式でアップロードします。組織で特定の認証局の証明書が求められる場合に便利です。証明書の有効期限は追跡されるため、期限切れになる前に更新できます。

ドメインのステータス

各ドメインには現在の状態を示すステータスバッジが表示されます:pending_verification(DNS 未確認)、verified(DNS 確認済み、TLS 保留中)、active(完全に稼働中)。

Domain list showing domains with status badges and verification controls

ドメイン一覧には、各カスタムドメインとその現在のステータスが表示されます

BYO certificate upload form with certificate and private key PEM fields

独自の TLS 証明書と秘密鍵を PEM 形式でアップロード

BYO 証明書の更新

BYO 証明書は更新を怠らないでください。証明書の有効期限が切れると、ユーザーのブラウザにセキュリティ警告が表示されます。

組織

組織とは、テナント内の顧客です。分離の境界はあくまでテナントです。テーブルプレフィックスと署名鍵はテナントごとに 1 つで、テナントの各ホストがそれぞれ独自の発行者(issuer)になります。組織はテナントの内部で ID を区分するため、顧客ごとにテナントを用意しなくても、1 つのテナントで多数の顧客組織に対応できます。

組織は、カスタムドメイン(ドメインを 1 つの組織に固定できます)やプロビジョニングアプリ(プロビジョニングアプリは新しいユーザーに組織のタグを付けられます)と並ぶ機能です。この機能の目的である「1 つのテナントで、ブランドの異なる多数の顧客」というパターンの全体像は、マルチカスタマーアプリガイドを参照してください。

モデルと ID

すべての組織には、org_id トークンクレームとして出力される安定した不変の id(org_<32 hex> 形式)と、org_slug として出力され、organization 認可パラメーターで受け付けられる、テナント内で一意な不変の slug があります。ID とスラッグは 1 つの検索名前空間を共有するため、別の組織の ID と同じスラッグは、通常のスラッグの重複とまったく同じく衝突として拒否されます。

フィールド変更可能説明
id不可org_id クレーム。org_ + GUID として発行されます。アンダースコアはスラッグに使えない文字のため、新しい ID がスラッグと衝突することはありません。
slug不可org_slug クレームで、organization パラメーターが受け付ける値です。リライングパーティーがハードコードするため、不変です。
name可<code>org_name</code> クレーム。自由に編集できます。
metadata可テナントが管理する自由形式のキーと値のペア。スコープのクレームセットが明示的に公開しない限り、トークンに出力されることはありません。
brandingJson可テナントのブランディングの上にフィールド単位でマージされる JSON オブジェクト。後述の「ブランディングのオーバーライド」を参照してください。
domainsドメインエンドポイントのみ組織が申請したメールドメインと、それぞれの所有を証明する DNS レコード。下記のドメインエンドポイント経由でのみ変更され、更新操作では変更されません。

メンバーシップ

メンバーシップは、ユーザーと組織の多対多の結合で、(組織、ユーザー)の組ごとに 1 行です。ユーザーは複数のメンバーシップを持てます。組織としてサインインすることを認可するのは、従来のユーザー単位の組織タグではなく、メンバーシップの行です。

ステータストークンを付与?
invited招待済みだが未承諾。トークンの発行は認可されません。
active正常な状態のメンバー。トークンの発行を認可する唯一のステータスです。
suspendedレコードを削除せずにメンバーシップを取り消した状態。トークンの発行は認可されません。

メンバーシップの roles はテナントの既存のロールカタログから選ばれ、roles クレームに統合されます。ただし、それはリクエストによって組織が明示的に選択された場合(「トークンの組織選択」を参照)で、かつアクティブなメンバーシップ行からのみです。ある組織で保持するロールが、別の組織向けに発行されたトークンに含まれることはありません。

組織への招待

POST /api/v1/users/invite は、任意で organizationId と organizationRoles を受け付けます。1 回の呼び出しで、invited メンバーシップを持つアカウントが作成され、組織のブランディングを適用した招待メールが送信されます。組織に固定されたカスタムドメインがある場合、リンクはそのドメインで開きます。本人が承諾すると、メンバーシップは active になります。組織を指定するには、オーナーまたは管理者である必要があります。

組織への SCIM プロビジョニング

SCIM トークンは組織に紐づけることができます(POST /api/v1/scim/tokens の organizationId、またはトークン作成時の組織ピッカー)。ID はテナントの組織を指している必要があります。そのトークンが作成するすべてのユーザーは active メンバーとなり、組織を org_id として保持します。紐づけは作成時にのみ適用され、決めるのはメンバーシップであってアクセス権ではありません。1 つのクライアント上の 2 つのトークンは、互いのユーザーを引き続き参照できます。ユーザーを削除すると、どの経路であってもそのメンバーシップは削除されます。

ポリシーフラグ

enabled(デフォルトはオン):無効化された組織は自組織向けのトークンを発行しません。これは認可時とすべてのリフレッシュ時の両方でチェックされるため、組織を無効化すると、新規ログインをブロックするだけでなく、ライブのセッションも次のローテーションで停止します。

requireMembershipForTokens(デフォルトはオン):この組織向けのトークンを発行するために、ユーザーがアクティブなメンバーシップを保持している必要があるかどうか。これが効くのは明示的な選択(組織を指定したリクエスト、組織を引き継いだリフレッシュ、組織スコープの接続、またはちょうど 1 つの組織に制限されたクライアント)の場合のみです。アカウント自身の従来のタグから継承されただけの組織が、このフラグで制限されることはありません。

allowAutoMembership(デフォルトはオフ):ユーザーの確認済みメールアドレスが組織の検証済みドメインのいずれかに属する場合、招待なしで参加できるようにします。認可時とすべてのリフレッシュ時に強制されます。後述の「メールドメインと自動メンバーシップ」を参照してください。

メールドメインと自動メンバーシップ

組織はメールドメインを申請し、DNS の TXT レコードでそのドメインを管理していることを証明します。allowAutoMembership がオンの場合、確認済みメールアドレスがそのドメインに属するユーザーは、その組織として初めてサインインしたときにメンバーになります。

  1. 申請する。ドメインを指定して POST /api/v1/organizations/{id}/domains を呼び出します。レスポンスは 201 で、recordName(_authagonal-org.acme.com)と recordValue(authagonal-org-verify=<token>)を返します。トークンはランダムで、申請ごとに異なります。
  2. レコードを公開する。ドメインの DNS に、その名前と値をそのまま使った TXT レコードを追加します。
  3. 検証する。POST /api/v1/organizations/{id}/domains/{domain}/verify がレコードを検索します。一致すると 200 と verified: true を返します。一致しない場合は 409 verification_failed を返し、verified: false 付きの 200 を返すことはありません。そのため、成功をポーリングするクライアントが不一致を成功と取り違えることはありません。
  4. 削除する。DELETE /api/v1/organizations/{id}/domains/{domain} は 204 を返します。既存のメンバーシップは残り、今後の自動参加だけが止まります。
POST /api/v1/organizations/{id}/domains
POST /api/v1/organizations/org_7fa2c9e1.../domains
Content-Type: application/json

{ "domain": "acme.com" }

201 Created
{
  "domain": "acme.com",
  "verified": false,
  "verifiedAt": null,
  "createdAt": "2026-10-03T01:02:03Z",
  "recordName": "_authagonal-org.acme.com",
  "recordValue": "authagonal-org-verify=Qm9...base64url"
}

拒否されるケース:400 domain_invalid(単純な DNS 名ではない)、409 domain_exists(この組織にすでに登録済み)、409 domain_taken(テナント内の別の組織が保持している)、404 organization_not_found、404 domain_not_found。1 つのドメインが属せるのはテナントごとに最大 1 つの組織で、これは検証時にも再度チェックされます。

自動メンバーシップのルール

セレクターは、アクティブなメンバーシップを持たないユーザーを、次の条件がすべて満たされる場合に受け入れます。

  • 組織が明示的に選択されていること:引き継がれたリフレッシュグラント、組織スコープの接続、organization パラメーター(ドメインの固定によって付与されるものを含む)、またはちょうど 1 つの組織に制限されたクライアント。アカウント自身の従来のタグで自動参加することはありません。
  • 組織が有効で、allowAutoMembership がオンであること。
  • ユーザーのメールが確認済みであること。誰でも [email protected] として登録できるためです。
  • メールアドレスの最後の @ より後の部分を小文字にしたものが、組織の検証済みドメインのいずれかと完全に一致すること。サブドメインの照合はありません。検証済みの acme.com では [email protected] は受け入れられません。各サブドメインはそれぞれ個別に申請して検証してください。

メンバーシップのゲートが実行される前に書き込まれる内容:行がない場合は、ロールなしの新しい active メンバーシップになります。invited の行は、ロールを保持したまま active に昇格します。active の行はそのままです。suspended の行が昇格することはありません。

メンバーを削除しても締め出せない

allowAutoMembership がオンの間は、削除されたメンバーでも条件を満たしていれば、次回の認可またはリフレッシュで再参加します。条件を満たすユーザーを締め出すには、そのメンバーシップを suspended に設定してください。これはルールが決して変更しない唯一の状態です。

トークンの組織選択

リクエストがどの組織に解決されるかは 1 か所でのみ決定されるため、/connect/authorize、すべてのリフレッシュ、デバイスグラントで結果は同一になります。優先順位(高い順):

#ソース動作
1引き継がれたグラント(リフレッシュ)以前のトークンの発行対象だった組織。その組織がもう存在しない場合、他にフォールバックせず、リフレッシュ自体が拒否されます。
2組織スコープの接続セッションが 1 つの組織に属する SAML または OIDC の接続を通じてサインインしたため、その組織が選択されます。主張ではなく証明に基づく唯一のソースです。別の組織を指定したリクエストは拒否され、接続の組織がもう存在しない場合も拒否されます。
3organizationスラッグを先に、次に ID で解決されます。ドメインの固定も同じ分岐に到達します。リクエストが評価される前に、ミドルウェアがそれを追加するためです。指定されたのに見つからない場合は確定的な拒否となり、黙ってフォールバックすることはありません。
4ちょうど 1 つの組織に制限されたクライアント自動的に選択されます。顧客ごとのアプリケーションは、1 つの組織を一度登録するだけで、パラメーターを送る必要がありません。ヒントなしで<em>複数の</em>組織に制限されている場合は、<code>account_selection_required</code> で拒否されます。
5アカウント自身の従来の組織タグ単一のフラットな文字列で、ユーザーのメンバーシップを走査するのではなく、1 回の検索で ID によって解決されます。実在する組織の行を指していない場合は、組織機能が導入される前とまったく同じく、制限なしでそのまま出力されます。明示的な選択には当たらないため、自動参加することはありません。
6上記のいずれでもないトークンに組織はまったく含まれません。<code>org_id</code>、<code>org_slug</code>、<code>org_name</code> のいずれのクレームもありません。

メンバーシップがヒントになることはない

アクティブなメンバーシップを複数持つユーザーが、どの組織も指定しないリクエストを送った場合、メンバーシップが 0 件のユーザーとまったく同じ動作になります。デフォルトを選ぶためにメンバーシップのテーブルが参照されることはありません。選択はそのままアカウント自身の従来のタグ(5 行目)に進み、それも空であれば、トークンには組織がまったく含まれません。メンバーシップが意味を持つのは、組織がすでに明示的に指定された後だけで、その時点で requireMembershipForTokens がチェックされ、該当する場合は自動参加が試行されます。

ドメインの固定

カスタムドメインは 1 つの組織に固定でき、そのドメインを組織専用の入り口にできます。固定はテナント解決ミドルウェアによって、GET /connect/authorize(クエリ文字列に追加)と POST /connect/par(PAR は保存されたペイロードからパラメーターを読むため、代わりにプッシュされた本文を書き換えます)の両方で強制されます。仕組みの詳細はカスタムドメインを参照してください。

PUT /api/v1/custom-domains/{domain}/organization
PUT /api/v1/custom-domains/auth.acme.com/organization
Content-Type: application/json

{ "organizationId": "org_7fa2c9e1..." }

固定されたドメインは矛盾するリクエストを拒否する

固定とは異なる組織を指定したリクエストは、ログインページを表示する前に 400 access_denied で直接拒否されます。これがなければ、リライングパーティーが独自の organization パラメーターを送れてしまい、固定は単なる飾りになってしまいます。

組織スコープの接続

SAML または OIDC の接続は、1 つの組織に属することができます。その接続を通じてサインインすると、その組織が選択され、ユーザーがメンバーシップを持っていなければ active メンバーシップが作成されます。invited の行は承諾済みとして扱われ、ロールと招待者を保持したまま active になるため、IdP を通じてサインインした招待者はメールを必要としません。suspended のメンバーは一時停止のままで、トークンの発行時に拒否されます。組織は接続によってすでに選ばれているため、これは allowAutoMembership にもドメインにも依存しません。

ログインページの組織名

ログインページでは、アプリ名の下に{name}にサインインしていますと表示されます。この名前は、ページのブランディングと同じ組織から取られます。固定されたドメインの組織、次に認可リクエストで指定された組織、次にクライアントが制限されている単一の組織の順です。組織がない場合、または組織名がアプリ名と同じ場合は非表示になるため、ヘッダーが「Acme / Acme にサインインしています」となることはありません。

ブランディングのオーバーライド

組織の brandingJson は、ログインページ用にテナントのブランディングの上へフィールド単位でマージされます。存在し null でないキーは上書きし、存在しないか null のキーは継承し、不明なキーは無視されます。不正な形式の JSON の場合は、警告をログに記録してテナント自身のブランディングにフォールバックし、ページの読み込みが失敗することはありません。

ブランディングタブでは、マージ可能な 21 個のフィールドすべてを編集できます:外観(appName、logoUrl、primaryColor、customCssUrl)、ライトモードとダークモードのカラー、メールのカラー、supportEmail、showForgotPassword、poweredBy、languages。各フィールドは、ヒントとして表示されるテナントの値を継承するか、それを上書きします。キーを削除するクリアの操作もあります。

showRegistration はオーバーライドできない

登録を提供するかどうかは、テナントの公開サインアップ設定ですでに決まっており、登録エンドポイントはブランディングにかかわらずそれを強制します。組織はその判断の権限を持たないため、このフィールドだけはマージから除外され、ブランディングタブにも操作項目がありません。

従来の組織タグからのバックフィル

組織機能が導入される前は、ユーザーは裏付けとなるレコードのない自由記述の組織タグを持つことができました。POST /api/v1/organizations/backfill は、それを従来の値ごとにグループ化して、実際の組織とメンバーシップに移行します。本文が { "dryRun": false } でない限り、ドライランとして実行されます。

  • 上限あり:1 回の呼び出しでスキャンするのは最大 50,000 ユーザーです。truncated レスポンスはもう一度実行する必要があることを意味し、再実行時には移行済みのユーザーはスキップされます。
  • 冪等:移行済みの従来の値は、組織の(編集可能な)表示名ではなく内部のスタンプで照合されるため、作成された組織の名前を後で変更しても、次回の実行で重複が生じることはありません。
レスポンスの例(ドライラン)
{
  "dryRun": true,
  "organizationsCreated": 3,
  "membershipsCreated": 41,
  "usersSkipped": 0,
  "organizations": [
    { "legacyValue": "acme-corp", "slug": "acme-corp", "users": 22 }
  ],
  "truncated": false
}

ポータル UI のウォークスルー

組織ページには、テナント内のすべての組織が 50 件ずつ表示され、さらに読み込むボタンがあります。また、新しい組織(スラッグと名前のみ。ポリシーフラグ、ドメイン、ブランディングは後で設定)と、上記のバックフィルをプレビューとして実行してから「適用」で反映する従来の組織フィールドからバックフィルフローがあります。

Organizations list showing slug, name, and created-date columns, with New Organisation and Backfill from legacy organisation field controls

組織一覧には、テナント内のすべての顧客組織が、スラッグ、名前、作成日とともに表示されます

各組織の詳細ページには 3 つのタブがあります:全般(名前、読み取り専用のスラッグ、3 つのポリシーの切り替え、メールドメインの追加・検証・削除と TXT レコードのコピーを行うメールドメインカード、スラッグを入力して確認する削除)、ブランディング(オーバーライド可能なすべてのフィールド。それぞれテナントの値を継承するか上書きします)、メンバー(メールで追加し、アカウントが存在しない場合は招待を提案。行ごとのステータス変更と削除、さらに読み込む)。

Organization detail page's Members tab showing invited, active, and suspended member rows with per-row status control

メンバータブには、各メンバーシップがステータスと、それを変更または削除する行ごとの操作とともに表示されます

Organization detail page's Branding tab with each overridable field showing either the tenant's inherited value or an override with a Clear control

ブランディングタブでは、この組織向けにテナントのログインページのブランディングをフィールド単位でオーバーライドします

ドメインページには、ドメイン → 組織のセレクターがあります。各ドメインカードには、テナントの組織と、固定を解除する「テナント(なし)」の選択肢を並べたインラインのドロップダウンがあり、変更するとすぐに適用されます。ドメインを追加するときにも同じセレクターが表示されます。

Domain card showing the inline organisation selector that pins a custom domain to one organisation

ドメインカード上のインラインの組織セレクターで、そのカスタムドメインを 1 つの組織に固定します

監査イベント

organization.created · organization.updated · organization.deleted · organization.member.added · organization.member.invited · organization.member.joined · organization.member.updated · organization.member.removed · organization.domain_added · organization.domain_verified · organization.domain_removed · organization.backfill · domain.organization_set

ページング

組織一覧とメンバー一覧はカーソルでページングされ、{ items, nextCursor } を返します。limit(デフォルトは 50、1 から 200 の範囲に制限)を渡し、2 ページ目以降は前回のレスポンスの nextCursor をそのまま cursor として渡します。nextCursor が null なら最後のページです。カーソルは組織 ID(メンバーの場合はユーザー ID)に対する不透明なキーセット位置のため、呼び出しの間に行が追加または削除されても、ページがずれたり重複したりすることはありません。一覧が発行していないカーソルは 400 invalid_cursor になります。

AI アシスタントからの組織の管理

ホスト型ポータル MCP は 13 個の組織ツールを公開しており、いずれもテナント管理者ロールが必要です:組織の一覧取得、取得、作成、更新、削除。メンバーの一覧取得、追加、更新、削除。メールドメインの追加、検証、削除。そしてユーザーの所属組織の一覧取得です。これらは上記の API と同じ操作を呼び出すため、ツールの動作がルートとずれることはありません。AI アシスタントからポータルを操作するを参照してください。

ホストごとに 1 つの発行者

テナントの各ホストは、それぞれ独自の OIDC 発行者です。リクエストのホストがテナントのドメインテーブルを通じて解決された場合、発行者とディスカバリーが公開するすべてのエンドポイント URL は https://{host} になります。そのため、アクティブな各カスタムドメインは独自の iss を示し、テナントの正規ホストは変わりません。署名鍵はテナントごとのため、すべてのホストが同じ鍵セットを提供します。これにより、1 つのテナントが複数の顧客の窓口となり、各顧客がそれぞれの組織に固定されたブランド独自のドメインを持てます。カスタムドメインを参照してください。

メール設定

テナントがトランザクションメール(確認、パスワードリセット、招待メールなど)を送信する方法を設定します。デフォルトの共有送信元、Resend 経由の確認済みカスタムドメイン、独自の SMTP サーバーから選択できます。

Email settings showing provider options (default, Resend domain, custom SMTP) and a test-send

ローカライズされたメール

トランザクションメールは、受信者の優先言語で送信されます。確認、パスワードリセット、アカウント既存通知、ウェルカム、招待、アカウント削除、サポート、請求の各メールには、英語、ドイツ語、フランス語、スペイン語、ポルトガル語、ベトナム語、簡体字中国語、日本語、アラビア語、ヒンディー語、アフリカーンス語の 11 のロケールのテンプレートがあります。受信者の言語のテンプレートがない場合は、英語で送信されます。

言語は、送信時に受信者の保存済みの言語設定から決定されます。この設定は、次のいずれかから設定されます:

  • サインアップと登録:ホストされたサインイン画面でユーザーが選択した言語が記録されます。
  • ポータルのユーザーページ:ユーザーの作成時または編集時に管理者が設定します。
  • SCIM プロビジョニング:SCIM 経由でユーザーが同期される際に、IdP の preferredLanguage(または locale)からマッピングされます。
  • セルフサービスのアカウントページ:ユーザー自身が /login/account で選択します。

設定は不要

ローカライズは自動で行われ、すべてのプロバイダーモード(デフォルト、Resend カスタムドメイン、SMTP)に適用されます。有効にする必要のある設定はありません。

メールプロバイダー

プロバイダー説明セットアップ
Authagonal (Default)共有の Resend インフラストラクチャを使い、[email protected] から送信されます。設定は不要です。そのまま使えます。
Custom Domain (Resend)Resend 経由で、確認済みの独自ドメインから送信されます。ドメインを登録し、DNS レコードを追加して、所有権を確認します。
Custom SMTP独自の SMTP サーバーを通じて送信されます。SMTP ホスト、ポート、認証情報、TLS 設定を指定します。

送信者情報

送信者メールアドレスと送信者名は、すべてのプロバイダーモードで共通です。カスタムドメイン(Resend)とカスタム SMTP のプロバイダーでは、送信者メールアドレスは必須です。送信者名が空の場合は、ブランディングのアプリ名が使われます。

フィールド説明
emailSenderEmail送信メールの From アドレス。カスタムドメイン(Resend)モードでは、確認済みドメインのアドレスである必要があります。
emailSenderName受信者の受信トレイに表示される表示名。

カスタムドメイン(Resend)

送信ドメインを Resend で一度確認すれば、このテナントの From アドレスとして使用できます。DNS レコード(SPF、DKIM)は、設定 → メール の「カスタム送信ドメイン」パネルに表示されます。Resend は、<strong>確認状況をチェック</strong> をクリックしたときにそれらを確認します。

カスタム SMTP

独自の SMTP サーバーを利用できます。社内リレー、Resend が対応していないベンダー、規制上の理由による送信経路の固定に役立ちます。

フィールド説明
smtpHostSMTP サーバーのホスト名(例:smtp.example.com)。
smtpPort接続ポート。デフォルトは 587 です。TLS は STARTTLS でネゴシエートされ、ポート 465 の暗黙的 TLS はサポートされていません。認証なしの社内リレーには 25 を使用します。
smtpUsername認証用のユーザー名(任意。認証なしのリレーの場合は空欄のままにします)。
smtpPassword認証用のパスワード。テナント設定のシークレットに暗号化して保存されます。
smtpUseTlsTLS を必須にします。信頼できる社内リレーを対象とする場合を除き、オンのままにしてください。

カスタム送信ドメイン

カスタムドメイン(Resend)プロバイダーを使用する場合、独自のドメインを登録して、@authagonal.io ではなく自社ブランドのアドレス(例:[email protected])からメールを送信できます。

  1. 設定 → メール に移動し、「カスタムドメイン(Resend)」プロバイダーを選択します。
  2. ドメイン名を入力し、「ドメインを登録」をクリックします。
  3. 表示された DNS レコード(DKIM、SPF、Return-Path)をドメインの DNS に追加します。
  4. 「確認状況をチェック」をクリックします。DNS が反映されると(通常 1〜10 分)、ドメインのステータスが確認済みに変わります。

DNS の反映

DNS の変更が世界中に反映されるまで最大 48 時間かかることがありますが、ほとんどのプロバイダーでは数分以内に更新されます。確認状況は何度でもチェックできます。

テスト

設定 → メール の「テストメールを送信」ボタンで設定を確認します。現在保存されている設定を使って、管理者のメールアドレスにテストメールが送信されます。

監査ログ

監査ログは、テナントに対して行われたすべての管理操作を読み取り専用で記録します。ポータルまたは API を通じて行われた変更は、すべて完全なコンテキストとともに記録されます。コンプライアンス対応やトラブルシューティングに必要な証跡を漏れなく確保できます。

ログの列

列説明
日時操作が行われた日付と時刻
実行者操作を行った管理者のメールアドレス。自動化された操作の場合は「system」
操作実行された操作の種類(例:クライアントを作成、設定を更新)
対象操作の対象。type:id 形式で表されます(例:client:my-app)
詳細変更に関する追加のコンテキスト

記録される操作

監査ログには、次の管理操作が記録されます:

カテゴリ操作
クライアントクライアントを作成、クライアントを更新、クライアントを削除
SSO 接続SAML 接続を作成、SAML 接続を削除、OIDC 接続を作成、OIDC 接続を削除
ユーザーユーザーを作成、ユーザーを更新
設定設定を更新、ブランディングを更新
ドメインドメインを追加、ドメインを検証、ドメインを削除
SCIMSCIM トークンを作成、SCIM トークンを取り消し
ロールロールを作成、ロールを更新、ロールを削除
グループグループを作成、グループを削除
チームチームメンバーを招待、チームメンバーを削除
Audit log table showing timestamped administrative actions with actor, action, entity, and detail columns

監査ログには、すべての管理操作が漏れなく記録されます

保持

監査ログは 365 日間保持され、変更や削除はできません。より長く保持するには、監査ログページの エクスポート タブで自動エクスポートを有効にしてください。

バックアップ

Authagonal は、テナントのデータを 1 時間ごとに自動でバックアップします。バックアップには、すべてのユーザー、グループ、ロール、クライアント、SSO 接続、SCIM トークン、ブランディング、設定が含まれます。バックアップページでは、バックアップ履歴を確認し、最新の完全なバックアップをダウンロードできます。

Backups page showing backup history with timestamps, types, and entity counts

バックアップの仕組み

  • 1 日 1 回、毎時の増分バックアップがまとめられて新しいフルバックアップになり、日曜日には日次のフルバックアップがまとめられて週次バックアップになります。日次バックアップは 7 個、週次バックアップは 4 個保持されます。
  • 増分バックアップは 1 時間ごとに実行され、前回のバックアップ以降に変更された行のみを取得します。
  • バックアップは、テナントが使用しているものと同じマネージド ID を使って Azure Blob Storage に保存されます。
  • 削除されたレコードはトゥームストーンで追跡され、監査の完全性のためにバックアップに含まれます。

バックアップのダウンロード

「最新をダウンロード」をクリックすると、最新のフルバックアップに、それ以降のすべての増分バックアップをマージした ZIP ファイルを取得できます。各テーブルは JSONL ファイル(1 行に 1 つの JSON オブジェクト)としてエクスポートされます。

バックアップの形式

バックアップは JSONL(JSON Lines)形式でエクスポートされます。テーブルごとに、1 行に 1 エンティティです。この形式は、解析、差分の比較、他のシステムへのインポートが容易です。

プロビジョニングアプリ

プロビジョニングアプリは、ユーザーが作成されるたびに Authagonal が呼び出す、お客様自身のサービスです。アカウントのセットアップ、ライセンスの割り当て、ユーザーが所属する組織の決定、あるいはサインアップそのものの拒否を行えます。

仕組み

ユーザーが作成されると、Authagonal は TCC(Try/Confirm/Cancel)パターンでプロビジョニングアプリのコールバック URL を呼び出します。いずれかのアプリがコミットされる前に、すべてのアプリが Try フェーズで受け入れる必要があります。そのため、作成途中のアカウントを残すことなく、複数のダウンストリームシステムが合意することも、1 つのシステムが拒否することもできます。

フェーズエンドポイント目的
/tryPOST {callbackUrl}/tryアプリがそのユーザーを処理できるかを確認します。受け入れる場合は 200、拒否する場合は 4xx を返します。
/confirmPOST {callbackUrl}/confirmすべてのアプリが /try フェーズで受け入れた後に、操作をコミットします。
/cancelPOST {callbackUrl}/cancel/try フェーズで別のアプリが失敗した場合に、操作をロールバックします。

プロビジョニングが実行されるタイミング

プロビジョニングは、セルフサービスのサインアップだけでなく、ユーザーを作成するすべての経路で実行されます。プロビジョニング済みのアプリとユーザーの組み合わせはスキップされるため、各アプリが同じユーザーを受け取るのは 1 回だけです。

作成経路実行タイミング
POST /api/auth/registerセルフサービス登録
SAML ACS コールバック新規ユーザーの初回 SSO ログイン(JIT)
OIDC コールバック新規ユーザーの初回 SSO ログイン(JIT)
POST /scim/v2/Usersコネクターが顧客のディレクトリからユーザーをプロビジョニングしたとき
ポータルおよび管理画面でのユーザー作成オペレーターが手動でユーザーを作成または招待したとき

Try リクエスト

Authagonal はこの JSON を <code>{callbackUrl}/try</code> に POST します。値のないフィールドは null として送信されず、省略されます。

フィールド型説明
transactionIdstringこのプロビジョニングトランザクションを識別します。同じ値が /confirm と /cancel にも送信されるため、この値に紐づけて処理をステージングし、該当する呼び出しが届いた時点でコミットまたは破棄してください。
userIdstringユーザーの Authagonal ID。ユーザーのトークンに含まれるサブジェクトです。
emailstringユーザーのメールアドレス。
firstNamestring名。作成経路で指定された場合に含まれます。
lastNamestring姓。作成経路で指定された場合に含まれます。
organizationIdstringユーザーがすでに所属している組織(ある場合)。以前に何らかの処理で割り当てられている場合にのみ含まれます。初回サインアップでは含まれないため、それが組織を割り当てる合図になります。
customAttributesobjectユーザーに保存されているカスタム属性。SSO で作成されたユーザーの場合は federated_connection が含まれます。これは、そのユーザーの身元を保証した接続の名前です。

想定しておくべき典型的なケースは、SSO 経由で到着するユーザーです。このユーザーにはまだ組織がなく、federated_connection を見れば、どの顧客から来たかがわかります。

SSO 接続経由で到着したユーザーの Try リクエスト
{
  "transactionId": "8f14e45fceea167a5a36dedd4bea2543",
  "userId": "0f6b1c8e-3d2a-4f51-9e77-2c1a4b5d6e7f",
  "email": "[email protected]",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "customAttributes": {
    "federated_connection": "acme-okta"
  }
}

Try レスポンス

アプリは 200 と JSON 本文で応答します。この本文は単なる受領確認ではありません。ダウンストリームのアプリは、この本文を使って、ユーザーのトークンに含まれる組織と属性を割り当てます。

フィールド型説明
approvedbooleanこのアプリがユーザーを受け入れるかどうか。省略した場合のデフォルトは true です。false の場合はサインアップが拒否され、新しいアカウントは削除されます。
reasonstringユーザーを拒否した理由。作成経路の呼び出し元に返されます。
organizationIdstringこのユーザーが所属する組織。ユーザーに保存され、トークンの org_id クレームとして発行されます。ユーザーにまだ組織がない場合にのみ適用されるため、最初に応答したアプリが優先され、後続のアプリにはその割り当てが渡されます。
customAttributesobjectユーザーにキー単位でマージする属性。スコープの UserClaims 設定を通じてトークンに含まれます。
emailVerifiedbooleanこのアドレスを確認済みであることをアプリが保証します(たとえば、そのアドレスに送った招待が使用された場合)。Authagonal はアカウントを確認済みにし、独自の確認メールを送信しません。
組織を割り当てる Try レスポンス
{
  "approved": true,
  "organizationId": "org_acme",
  "customAttributes": { "org_role": "member" }
}

org_id の出どころ

アカウントの組織タグ、つまりリクエストで組織が指定されていない場合の org_id クレームは、プロビジョニングアプリが organizationId として返した値そのものです。その値がテナント内の組織の ID である場合、トークンにはその組織の org_id、org_slug、org_name が含まれ、無効化された組織ではサインインが拒否されます。それ以外の値は org_id としてそのまま出力され、一意性のルールも形式の要件もありません。組織 ID を返しても、メンバーシップは作成されません。PUT /api/v1/users/{userId} で直接設定することも、GET /api/v1/users?organizationId= で絞り込むこともできます。

ユーザーに正しい組織をタグ付けする

組織は作成経路ごとに決めるのではなく、ここ 1 か所で決定してください。SSO ユーザーは federated_connection を持っています。これにより、そのユーザーを認証した接続、つまり顧客を特定でき、1 つの顧客が複数のメールドメインをフェデレーションしている場合でも正しく判別できます。招待されたユーザーには接続がないため、発行した招待で照合してください。どちらの経路もユーザーが存在する前に /try に到達するため、1 つのロジックで両方に対応でき、食い違いかねない 2 つのルールを持つ必要もありません。

Try コールバックで組織を解決する
// POST {callbackUrl}/try
app.post('/provisioning/try', async (req, res) => {
  const { email, customAttributes } = req.body;

  // An SSO user carries the connection that vouched for them. That is the
  // customer, and it stays right when one customer has several domains.
  const connection = customAttributes?.federated_connection;

  const org = connection
    ? await orgByConnection(connection)
    : await orgByPendingInvite(email);

  if (!org) return res.json({ approved: false, reason: 'No organization for this user' });

  // Stamped on the user and emitted as org_id on every token from now on.
  res.json({ approved: true, organizationId: org.id });
});

拒否するとアカウントは削除される

いずれかのアプリが approved: false と応答した場合、新しく作成されたユーザーは削除され、プロビジョニングが中途半端なアカウントは残りません。API の作成経路は理由とともに 422 を返し、SAML および OIDC のコールバックは 400 を返します。処理することがないユーザーに対しては approved: true を返してください。

プロビジョニングアプリの追加

プロビジョニングアプリを追加するには、アプリ名、コールバック URL、任意の API キー、任意の Try のタイムアウト(秒。デフォルトは 60、範囲は 5 から 300。Confirm と Cancel には固定の短いタイムアウトが使われます)を指定します。API キーは各ウェブフックリクエストの Authorization ヘッダーで Bearer トークンとして送信されるため、アプリは Authagonal からのリクエストを認証できます。

テスト

プロビジョニングアプリの横にあるテストをクリックすると、コールバック URL にテストリクエストが送信されます。テスト結果には HTTP ステータスコードとレスポンス本文が表示されるため、アプリがウェブフックを正しく受信して処理しているかを確認できます。

Provisioning apps page showing configured apps with test results displaying HTTP status and response body

プロビジョニングアプリをテストして、ウェブフックの配信とレスポンスの処理を確認

プランの上限

プロビジョニングアプリの最大数はテナントごとに設定でき、デフォルトの上限は 6 です。ワークフローでさらに多くのプロビジョニング先が必要な場合は、管理者がこの上限を調整できます。

API キー認証

API キーが設定されている場合、Authorization ヘッダーで Bearer トークンとして送信されます。Authagonal からのウェブフックリクエストの認証に使用してください。

チーム

チームページでは、ポータル管理者、つまり管理ポータルを通じてテナントにアクセスし、設定を行えるユーザーを管理します。各チームメンバーにはロール(オーナー、管理者、開発者、サポート)があり、それによって変更できる内容が決まります。

管理者一覧

管理者一覧には、各チームメンバーの名前、メールアドレス、ロール、追加された日付が表示されます。現在のユーザーの行には「あなた」の表示が付くため、自分のアカウントを簡単に見分けられます。

管理者の招待

新しいチームメンバーを招待するには、メールアドレス、名前、ロールを指定します。招待されたユーザーには、パスワードを設定してアカウントを有効化するためのリンクが記載されたメールが届きます。リンクの有効期間は 7 日間です。

招待のフィールド

管理者の招待では、保留中のアカウントが作成され、招待されたユーザーに有効化リンクがメールで送信されます。

フィールド説明
email新しい管理者のメールアドレス。テナント内で一意である必要があります。
name管理者一覧に表示される表示名。
role付与するロール:tenant:admin、tenant:developer、tenant:support のいずれか。デフォルトは tenant:admin です。オーナーロールは招待では付与できません。

管理者の削除

テナントオーナーは、チームメンバーの横にある削除をクリックして、そのメンバーのアクセス権を取り消せます。削除が確定する前に、確認ダイアログが表示されます。自分自身を削除することはできず、テナントのオーナーは常に維持されます。

Team page showing the admin list with name, email, date added columns, a You indicator, and invite/remove controls

チームページでポータル管理者を管理

所有権

各テナントにはオーナーが 1 人います。チームメンバーの削除や、別のメンバーに対する オーナーにする による所有権の移譲を行えるのはオーナーだけです。以前のオーナーは管理者になります。

サポート

ポータルを離れることなく、Authagonal チームへのサポートチケットを作成できます。各チケットはスレッド形式の会話なので、最初の報告から解決まで、お客様と当社チームが同じ認識を保てます。

お客様のチケット

サポートページには、お客様が作成したすべてのチケットが、最新のアクティビティ順に一覧表示されます。ステータスバッジを見れば、お客様の対応待ちのものと当社の対応待ちのものが一目でわかります。

Support ticket list showing each ticket's subject, status badge, priority, and last-activity time, with a New ticket button

件名、ステータス、優先度、最終アクティビティを表示したサポートチケット一覧

  • 各行には、件名、現在のステータス(オープン、保留中、解決済み、クローズ済み)、優先度、最終アクティビティの日時が表示されます。
  • 新しいチケットをクリックしてチケットを作成し、件名、優先度、最初のメッセージを入力します。
  • 色分けされたステータスバッジにより、対応が必要なチケットを一覧から簡単に見つけられます。

チケットのスレッド

チケットを開くと、会話全体が表示されます。返信は順番に投稿され、当社チームからの新しいメッセージはページを再読み込みしなくても表示されます。

Support ticket thread showing the conversation between the customer and the Authagonal team with a reply box and file attachment control

お客様と Authagonal チームとのチケットのスレッド

  • お客様と Authagonal チームとのスレッド形式のメッセージが、時系列で表示されます。
  • その場で返信し、ファイルを添付してログ、スクリーンショット、設定を共有できます。
  • スレッドはリアルタイムで更新されるため、当社チームからの返信は送信されるとすぐに表示されます。
  • 通知メールに返信した場合も、メッセージは自動的にスレッドに追加されます。

返信が届く仕組み

Authagonal のスタッフは、管理側でチケットに対応します。チームが返信するたびにメールで通知されるため、会話を追うためにポータルを開いたままにしておく必要はありません。

ユーザー向けサポートデスク

当社から受けるサポートとは別に、Authagonal はお客様のエンドユーザー向けのサポートデスクを運用できます。エンドユーザーはテナント独自のブランド付きホスト上のアカウントページからチケットを作成し、お客様のチームはポータルから回答します。

この機能があるのは、サインインできない人こそ、サインインが必要なサポートツールにたどり着けない人だからです。デスクはログイン画面と並んで置かれているため、ロックアウトされたユーザーにも連絡手段が残ります。また、すべてのチケットは、誰かが入力したアドレスではなく、ディレクトリ内の実在するアカウントにあらかじめ紐づいた状態で届きます。

有効にする

ポータルで カスタマーサポート を開き、設定 タブに切り替えて カスタマーサポートを有効化 をオンにします。このタブはオーナーと管理者に表示されます。有効にするまで、ユーザーには何も表示されません。

設定機能
カスタマーサポートを有効化マスタースイッチです。オフの場合、エンドユーザー向けページとオペレーター用の受信トレイはどちらも非表示になり、それらの API は 404 を返します。
サインインしていない訪問者からのリクエストを許可サインインしていない訪問者がチケットを作成できるようにします。ロックアウトされたケースに対応するためのものです。ボット対策で保護されており、サインインするアカウントがないため、やり取りはメールと非公開リンクで続きます。
メール通知チケットが届いたときやユーザーが返信したときにメールで通知する相手です。通知しない、特定のアドレス、サポートチーム全体(オーナー、管理者、サポート)から選べるため、誰かが受信トレイを見張り続ける必要がなくなります。
顧客のデフォルト言語ユーザーの言語がまだわからない場合に、そのユーザーのチケットとメールで想定する言語です。ユーザー自身が保存した言語が常に優先され、何も設定されていない場合は英語になります。この設定は、設定の <strong>全般</strong> タブにあります。
サポートウェブフック URLチケットのイベントを POST する URL。イベントを自社のツールに送り込むために使います。

Free プランでは利用不可

サポートデスクは、Free プランに含まれない唯一の機能です。受信メールと翻訳には、利用ごとに実際のコストがかかるためです。有料プランにはすべて含まれます。認証機能がこのように制限されることはありません。シングルサインオン、SCIM、多要素認証、カスタムドメイン、ブランディング、監査は、Free を含むすべてのプランで利用できます。

ユーザーに表示される内容

サインイン済みのユーザーには、テナントホスト上のアカウントページに、お客様のブランディングが適用されたサポートエリアが表示されます。ユーザーはチケットの作成、自分が作成したすべてのチケットの確認、スレッドでの返信ができます。チームからの返信はメールでも届くため、ユーザーがページを確認し続ける必要はありません。

匿名チケットを有効にすると、サインインできない人でもチケットを作成できます。メールアドレスとメッセージを入力すると、会話への非公開リンクが返されます。このリンクが唯一のアクセス手段なので、資格情報として扱ってください。推測はできませんが、リンクを持っている人は誰でもその1つのスレッドを閲覧し、返信できます。

オペレーター用受信トレイ

チームはポータルのサイドメニューにあるカスタマーサポートから回答します。これはお客様が当社に送るチケットとは別の場所で、tenant:support ロール以上で利用できます。そのため、ポータルの他の部分へのアクセスを与えずに、担当者にデスクへのアクセスだけを与えられます。

操作機能
返信スレッドに投稿します。ユーザーにはメールが届き、ページを開いていればリアルタイムで表示されます。
割り当てチケットをチームの特定のメンバーに割り当て、2人が同じチケットに回答しないようにします。
ステータスと優先度チケットをオープン、保留中、解決済み、クローズ済みの間で移動し、緊急度を設定します。クローズ済みのチケットは永久に保持されず、保持期間の経過後に削除されます。
内部メモチームだけに表示され、ユーザーには決して表示されないメモ。編集と削除は監査ログに記録されます。
ユーザーに代わってチケットを作成会話が別の場所で始まった場合に、ディレクトリからユーザーを選んで、そのユーザーとのスレッドを開始します。
Authagonal にエスカレーションチケットがお客様の製品ではなく Authagonal に関するものだと判明した場合は、エスカレーションします。当社チームとの間にリンクされたチケットが作成され、必要に応じてそれまでのスレッドも引き継がれます。2つのチケットは紐づけられるため、両方の経過を追えます。チケットのエスカレーションは1回だけです。

ユーザーは自分の言語で書ける

チケットはユーザーが書いた言語で保存され、スレッドの各参加者はそれぞれ自分の言語で読みます。担当者にはポータルの言語に翻訳されたメッセージが表示され、ユーザーにはお客様の返信がユーザーの言語に翻訳されて表示されます。原文は常に併せて保持されます。言語は最初のメッセージから判定され、チケットに固定されます。翻訳は言語ごとに一度だけ計算されて再利用されるため、長いスレッドでも翻訳がやり直されることはありません。

タイムゾーン

チケットには、ユーザーがチケットを作成したときのタイムゾーンが記録されます。各メッセージには、ユーザーの現地時刻がお客様の時刻と並べて表示されるため、14:32 の返信が、待っている相手にとっては実際には 02:32 だったと分かります。メールで届いたチケットなどタイムゾーンが不明な場合や、お客様のタイムゾーンと同じ場合は何も表示されません。

ウェブフック

サポートウェブフック URL を設定すると、チケットのイベントを発生と同時に受け取れます。アラートを出したり、チケットを自社のシステムにミラーしたりするために使います。ペイロードには署名が付いているため、当社から送られたものか検証できます。

イベント機能
support.ticket.createdユーザーがチケットを作成しました。
support.ticket.messageユーザーまたはお客様のオペレーターによって、スレッドにメッセージが投稿されました。どちらが投稿したかは、ペイロードの fromStaff でわかります。
support.ticket.status_changedチケットのステータスが変更されました(例:解決済み)。
support.ticket.assignedチケットがチームメンバーに割り当てられました。

インポートと移行

既存の ID システムを Authagonal テナントに移行します。サポートされているソースは、Duende IdentityServer(SQL Server データベース)と Auth0(Management API)の 2 つです。どちらも読み取り専用のプレビューを実行するため、コミットする前に、コピーされる内容を正確に確認できます。

Duende IdentityServer からのインポート

既存の Duende IdentityServer の SQL Server データベースから、クライアント、スコープ、ユーザー、ロールを Authagonal テナントに移行します。インポートはプレビューとコミットの 2 段階で実行されるため、変更が加えられる前に、コピーされる内容を確認できます。

インポートされるもの

インポーターは Duende の ConfigurationDb と ASP.NET Identity のテーブルを読み取り、マッピングした行をテナントに書き込みます。永続化されたグラント、デバイスコード、署名鍵などの短命なデータはスキップされます。

エンティティソーステーブル備考
クライアントClients, ClientSecrets, ClientGrantTypes, ClientScopes, ClientRedirectUris無効なクライアントは、無効のままインポートされます。期限切れのシークレットはスキップされます。
スコープApiScopes, ApiResources, IdentityResources認識できるユーザークレームのマッピングは保持されます。
ユーザーAspNetUsers, AspNetUserClaimsパスワードハッシュ(ASP.NET Identity V3)はそのままコピーされ、初回ログイン時に再ハッシュされます。
ロールAspNetRoles, AspNetUserRolesロールの割り当ては保持されます。
外部ログインAspNetUserLogins参照用に保存されます。インポート後、SSO でアップストリームの IdP を再接続してください。

コミット前のプレビュー

Duende の ConfigurationDb / IdentityDb の接続文字列を貼り付け、プレビューを実行をクリックします。プレビューは読み取り専用の接続を開き、インポートされるすべての行を数えます。書き込みは一切行われません。

  • クライアント、スコープ、ユーザー、ロール、ロールの割り当ての各エンティティ数。
  • 対象テナントにすでにクライアント(ClientId が一致するものは上書きされます)、ロール、スコープ(名前が一致するものはスキップされます)が存在する場合の競合警告。
  • 不明なテーブルと、マッピングされていない列に関する警告。何が破棄されるかを把握できます。
Import preview panel showing entity counts and warnings before committing the import

件数と警告が表示されたプレビューパネル

パスワードハッシュ

Duende は ASP.NET Identity V3(PBKDF2)でパスワードを保存します。Authagonal の PasswordHasher はこの形式を直接検証し、初回のサインインに成功した時点でネイティブ形式に再ハッシュします。ユーザーはリセットの手続きなしで、既存のパスワードをそのまま使えます。

ユーザー ID の照合

このテナントにすでに存在するユーザーが、受信レコードと同じメールアドレスを持つ場合、インポートはその前に、そのアカウントの userId をソースの sub に付け替えます。これにより、インポートされたロール、ログイン、クレームが既存のアカウントに紐づき、ソースの sub でユーザーを参照しているアプリは、カットオーバー後も引き続き解決できます。アカウントの既存のパスワードとプロフィールは保持され、ソースのロールはその上にマージされます。照合されるすべてのアカウントは、コミット前にプレビューで一覧表示されます。

インポートの実行

プレビューを確認したら、インポートを開始をクリックします。コミットフェーズでは、クライアント、スコープ、ユーザー、ロール、外部ログインの参照がテナントのストアに書き込まれます。clientId が一致するクライアントは上書きされ、scope name、email、role name が一致する行はスキップされるため、インポーターは安全に再実行できます。

インポートされないもの

  • 永続化されたグラント、デバイスコード、サーバー側セッション:短命なデータであり、自動的に再生成されます。
  • 署名鍵:Authagonal はテナントごとに独自の鍵を発行します。
  • カスタムの列とテーブル:Duende の標準スキーマに含まれないものはすべて警告として表示されるため、そのデータが破棄されたことを把握できます。
  • 無効なクライアント:無効な状態でインポートされます。準備ができたら、クライアントページで再度有効にしてください。

サンドボックスでは利用不可

インポートはライブテナントに対してのみ実行されます。インポートする前に、サンドボックスモードを終了してください。

Auth0 からのインポート

Authagonal を Auth0 テナントの Management API に接続し、アプリケーション、API、ロール、ユーザー、エンタープライズ接続を移行します。インポートされたユーザー ID とアプリケーション ID は保持されるため、既存の sub と client_id の参照はカットオーバー後も引き続き解決されます。

必要なもの

Auth0 で、Management API へのアクセスを許可されたMachine-to-Machine アプリケーションを作成し、次の読み取りスコープを付与します:read:users、read:clients、read:resource_servers、read:roles、read:connections、read:client_grants。そのドメイン、クライアント ID、クライアントシークレットをインポートフォームに貼り付けてください。これらはインポートにのみ使用されます。

インポートされるもの

エンティティソーステーブル備考
アプリケーションclients, client-grantsパブリックかコンフィデンシャルかは自動的に検出されます。クライアントシークレットは再ハッシュされるため、引き続き機能します。
API とスコープresource-serversオーディエンスとスコープは、各クライアントのグラントに基づいて割り当てられます。
ロールroles + 割り当てユーザーごとのロールの割り当ては保持されます。
ユーザーusers + identitiesプロフィールとメタデータが移行されます。ソーシャル/エンタープライズ ID は、リンクされたログインになります。
接続connections(OIDC)エンタープライズ OIDC 接続は、フェデレーションプロバイダーになります。SAML、ソーシャル、データベースの接続は、警告付きでスキップされます。

パスワード

Auth0 の Management API がパスワードハッシュを返すことはありません。Auth0 のサポートを通じた一括パスワードエクスポート(NDJSON)がある場合は、それを指定してください。bcrypt ハッシュはそのままインポートされ、ユーザーはリセットなしで既存のパスワードを使い続けられます。このファイルにはユーザー全体のデータも含まれるため、Auth0 API の一覧取得における 1,000 ユーザーの上限もなくなります。ファイルがない場合、ユーザーはプロフィールとしてインポートされ、初回サインイン時に新しいパスワードを設定します。

プレビュー、付け替え、制限は共通

上記で説明したプレビュー、オーナーの userId の付け替え、再実行可能なコミット、サンドボックスでの制限は、Auth0 のインポートにも適用されます。

API リファレンス

各テナントは、https://{slug}.authagonal.io で標準準拠の OIDC サーバーを公開しています。すべてのエンドポイントは OAuth 2.0 および OpenID Connect の仕様に準拠しています。このリファレンスでは、アプリケーションが利用する可能性のあるすべてのエンドポイントを説明します。

OIDC Authorization Code Flow with PKCE: sequence diagram showing the 9-step flow between your app, the browser, and Authagonal

PKCE を使用した Authorization Code フロー

OIDC ディスカバリーと JWKS

ディスカバリードキュメントを使うと、OIDC クライアントライブラリが自動的に構成されます。どちらのエンドポイントも認証は不要です。

GET /.well-known/openid-configuration

OpenID Provider Configuration ドキュメントを返します。レスポンスには、クライアントがこのテナントとやり取りするために必要なすべてのメタデータが含まれます。

フィールド説明
issuerテナントの発行者 URL
authorization_endpoint認可リクエストの URL
token_endpointトークン交換の URL
userinfo_endpointユーザークレームを取得する URL
jwks_uriJSON Web Key Set の URL
revocation_endpointトークン取り消しの URL
introspection_endpointトークンイントロスペクションの URL
end_session_endpointログアウト/セッション終了の URL
device_authorization_endpointデバイス認可リクエストの URL
pushed_authorization_request_endpointPushed Authorization Request エンドポイントの URL(RFC 9126)。
require_pushed_authorization_requestsテナントがグローバルに PAR を必須としているかどうか。これが false の場合でも、個々のクライアントで RequirePushedAuthorizationRequests = true を設定できます。
scopes_supportedサポートされているスコープの一覧
response_types_supportedサポートされているレスポンスタイプ
grant_types_supportedサポートされているグラントタイプ
code_challenge_methods_supportedサポートされている PKCE メソッド(S256)
backchannel_logout_supportedバックチャネルログアウトがサポートされているかどうか

GET /.well-known/openid-configuration/jwks

トークン署名の検証に使用する JSON Web Key Set を返します。レスポンスには EC P-256 公開鍵の keys 配列が含まれ(トークンは ES256 で署名されます)、各要素は kty(EC)、use、kid、alg、crv、x、y フィールドを持ちます。

Fetch discovery document
curl https://acme.authagonal.io/.well-known/openid-configuration

認可エンドポイント

GET /connect/authorize

認可コードフローを開始します。ユーザーにアクティブなセッションがない場合は、ログインページにリダイレクトされます。成功すると、ユーザーは認可コードとともにアプリケーションにリダイレクトされます。

パラメーター必須説明
response_typeはい"code" である必要があります
client_idはい登録済みのクライアント識別子
redirect_uriはい登録済みのリダイレクト URI と完全に一致する必要があります
scopeはいスペース区切りのスコープの一覧(例:"openid profile email")
state推奨CSRF 対策用の不透明な値。リダイレクト時に変更されずに返されます
code_challengePKCE 使用時は必須code_verifier の SHA-256 ハッシュを Base64url エンコードした値
code_challenge_methodPKCE 使用時は必須"S256" である必要があります
nonce任意リプレイ対策のために ID トークンに紐づけられる値
login_hint任意ログインページのメールアドレス欄に事前入力する値

成功時のレスポンス:redirect_uri への 302 リダイレクト。code と state のクエリパラメーターが付与されます。

エラー時のレスポンス:error、error_description、state のクエリパラメーターを付けた 302 リダイレクト。

PKCE は必須

PKCE は、デフォルトですべてのクライアントに必須です。code_verifier(43 文字以上のランダムな文字列)を生成し、SHA-256 でハッシュ化して、その結果を base64url エンコードし、code_challenge を作成します。

Pushed Authorization Requests(PAR)

RFC 9126。すべての authorize パラメーターを URL に載せる代わりに、クライアントは通常のクライアント認証を使ってそれらを /connect/par に POST し、有効期間の短い不透明な request_uri を受け取ります。その後、ブラウザーは /connect/authorize?client_id=...&request_uri=... にアクセスします。それ以外の情報がブラウザー履歴、サーバーログ、Referer ヘッダーに残ることはなく、サーバーはクライアント認証のもとで、パラメーターの完全性をすでに確認しています。

POST /connect/par

クライアント認証は /connect/token と同じです。client_id/client_secret による HTTP Basic 認証、またはフォームエンコードされた認証情報を使用します。パブリッククライアントは、シークレットなしで POST します。本文には、通常 /connect/authorize に送信するものと同じパラメーターを含めます。request_uri 自体は拒否されます(PAR の連鎖は仕様の §2.1 で禁止されています)。201 Created を返します。

パラメーター必須説明
client_idはいクライアント ID。認証されたクライアントと一致する必要があります。
client_secretコンフィデンシャルクライアントクライアントシークレット。コンフィデンシャルクライアントでは必須です。
response_typeはい"code" である必要があります
redirect_uriはい登録済みのリダイレクト URI と完全に一致する必要があります
scopeはいスペース区切りのスコープの一覧(例:"openid profile email")
code_challengePKCE 使用時は必須code_verifier の SHA-256 ハッシュを Base64url エンコードした値
code_challenge_methodPKCE 使用時は必須"S256" である必要があります
state推奨CSRF 対策用の不透明な値。リダイレクト時に変更されずに返されます
nonce任意リプレイ対策のために ID トークンに紐づけられる値

レスポンス

フィールド説明
request_uri1 回だけ使用できる不透明な参照(例:<code>urn:ietf:params:oauth:request_uri:abc123…</code>)。<code>/connect/authorize</code> に <code>request_uri</code> として渡します。
expires_in<code>request_uri</code> の有効期間(秒)。デフォルトは 90 で、リファレンス IdP の一般的な値です。

後続の GET /connect/authorize?client_id=…&request_uri=… では、他のすべてのパラメーターがプッシュされたペイロードから取得され、追加のクエリパラメーターは無視されます。authorize 呼び出しの client_id は、リクエストをプッシュしたクライアントと一致する必要があります。一度使用されると(または expires_in が経過すると)、request_uri はストアから削除されます。

クライアントごとに PAR を強制する

クライアントで プッシュ型認可リクエストを必須にする をオンにすると(ポータルの「クライアント」で対象のクライアントを開き、セキュリティ タブ)、そのクライアントからの通常の /connect/authorize 呼び出しが拒否されます。リスクの高いクライアントに推奨される構成は、RequirePushedAuthorizationRequests = true と PKCE の組み合わせです。これにより、URL バーという攻撃対象領域が完全になくなります。
Push an authorization request and follow up
# 1. Push parameters (server returns request_uri + expires_in)
curl -X POST https://acme.authagonal.io/connect/par \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "response_type=code" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "scope=openid profile email" \
  -d "state=$(openssl rand -hex 16)" \
  -d "code_challenge=YOUR_CODE_CHALLENGE" \
  -d "code_challenge_method=S256"

# 2. Send the user to /authorize with only client_id + request_uri
# https://acme.authagonal.io/connect/authorize?client_id=my-app&request_uri=urn:ietf:params:oauth:request_uri:abc123...

トークンエンドポイント

POST /connect/token

認証情報をトークンと交換します。リクエストには Content-Type: application/x-www-form-urlencoded を使用する必要があります。クライアント認証は、HTTP Basic 認証(Authorization: Basic base64(client_id:client_secret))またはフォーム本文のパラメーター(client_id + client_secret)で指定できます。

Authorization Code グラント

パラメーター必須説明
grant_typeはい"authorization_code"
codeはいリダイレクトで受け取った認可コード
redirect_uriはい認可リクエストで使用した URI と一致する必要があります
code_verifierPKCE 使用時は必須code_challenge の生成に使用した元のランダムな文字列
client_idはいクライアント識別子(Basic 認証を使用しない場合)
client_secretコンフィデンシャルクライアントクライアントシークレット(Basic 認証を使用しない場合)

Refresh Token グラント

パラメーター必須説明
grant_typeはい"refresh_token"
refresh_tokenはい交換するリフレッシュトークン
client_idはいクライアント識別子
client_secretコンフィデンシャルクライアントクライアントシークレット

Client Credentials グラント

パラメーター必須説明
grant_typeはい"client_credentials"
client_idはいクライアント識別子
client_secretはいクライアントシークレット
scope任意要求するスコープ(スペース区切り)

Device Code グラント

パラメーター必須説明
grant_typeはい"urn:ietf:params:oauth:grant-type:device_code"
device_codeはいデバイス認可レスポンスで受け取ったデバイスコード
client_idはいクライアント識別子
client_secretコンフィデンシャルクライアントクライアントシークレット

トークンレスポンス:

フィールド説明
access_tokenAPI 呼び出し用のアクセストークン
token_type"Bearer"
expires_inトークンの有効期間(秒)
id_tokenOpenID Connect の ID トークン(openid スコープを要求した場合)
refresh_tokenリフレッシュトークン(offline_access スコープが付与された場合)
Exchange authorization code with PKCE
curl -X POST https://acme.authagonal.io/connect/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=AUTHORIZATION_CODE" \
  -d "redirect_uri=https://app.example.com/callback" \
  -d "client_id=my-app" \
  -d "code_verifier=YOUR_CODE_VERIFIER"

UserInfo エンドポイント

GET /connect/userinfo

認証済みユーザーに関するクレームを返します。openid スコープを持つ有効なアクセストークンが必要です。

フィールド型説明
substring一意のユーザー識別子
emailstringユーザーのメールアドレス
email_verifiedbooleanメールアドレスが確認済みかどうか
given_namestring名
family_namestring姓
namestringフルネームの表示名
phone_numberstring電話番号(指定されている場合)。<code>phone</code> スコープで出力されます。
org_idstringユーザーが所属する組織。お客様自身のプロビジョニングアプリが割り当てるか(プロビジョニングアプリを参照)、PUT /api/v1/users/{userId} で設定します。Authagonal がこの値を導出することはありません。profile スコープで提供され、ユーザーに組織がない場合は含まれません。
rolesstring[]割り当てられたロールの配列。トークンが <code>roles</code> スコープを持つ場合にのみ出力されます。
groupsobject[]所属グループの配列。各要素は id と name を持ちます。トークンが <code>groups</code> スコープを持つ場合にのみ出力されます。
Fetch user info
curl https://acme.authagonal.io/connect/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"

トークンイントロスペクション(RFC 7662)

POST /connect/introspect

トークンを検証し、そのメタデータを返します。クライアント認証情報(Basic 認証またはフォーム本文のパラメーター)が必要です。

パラメーター必須説明
tokenはいイントロスペクトするトークン
token_type_hint任意トークンの種類に関するヒント(例:"refresh_token")

アクティブなトークンのレスポンス:

フィールド説明
activetrue
subサブジェクト(ユーザー ID)
client_idトークンの発行先クライアント
scope付与されたスコープ(スペース区切り)
iss発行者
exp有効期限(Unix タイムスタンプ)
iat発行日時(Unix タイムスタンプ)
audオーディエンス
token_typeトークンの種類(例:"Bearer")

非アクティブなトークンのレスポンス:{ "active": false }

常に 200 OK

RFC 7662 に従い、イントロスペクションエンドポイントはどのトークンに対しても 200 OK を返すため、トークンの列挙には利用できません。無効、期限切れ、または取り消されたトークンに対しては、単に active: false が返されます。唯一の例外は呼び出し元自身です。認証に失敗したクライアントには 401 invalid_client が返されます。
Introspect a token
curl -X POST https://acme.authagonal.io/connect/introspect \
  -u "my-app:CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=ACCESS_OR_REFRESH_TOKEN"

トークンの取り消し(RFC 7009)

POST /connect/revocation

以前に発行されたトークンを取り消します。クライアント認証情報が必要です。

パラメーター必須説明
tokenはい取り消すトークン
token_type_hint任意トークンの種類に関するヒント(例:"refresh_token")

RFC 7009 の仕様に従い、このエンドポイントは、無効なトークンやすでに取り消されたトークンに対しても、常に 200 OK を返します。

アクセストークンとリフレッシュトークン

リフレッシュトークンとアクセストークンのどちらも取り消せます。リフレッシュトークンを取り消すと、そのリフレッシュトークンから発行されたアクセストークンも取り消されます。取り消されたアクセストークンはイントロスペクションと userinfo で拒否されますが、JWT をローカルで検証するリソースサーバーは有効期限が切れるまで受け入れ続けます。そのため、アクセストークンの有効期間は短くしておいてください。

デバイス認可(RFC 8628)

POST /connect/deviceauthorization

入力手段が限られたデバイス(CLI、スマートテレビ、IoT デバイス)向けのデバイス認可フローを開始します。デバイスがユーザーにコードを表示し、ユーザーはブラウザーのある別のデバイスでリクエストを承認します。

パラメーター必須説明
client_idはいクライアント識別子
client_secretコンフィデンシャルクライアントクライアントシークレット
scope任意スペース区切りのスコープ(デフォルトは "openid")

レスポンス:

フィールド説明
device_codeデバイスの検証コード(ポーリングに使用)
user_codeユーザーに表示する XXXX-XXXX 形式のコード
verification_uriユーザーがコードを入力するためにアクセスする URL
verification_uri_completeuser_code が事前入力された URL
expires_inデフォルトは 300(秒。コードの有効期間は 5 分です)。クライアントごとに設定します。
interval5(秒。ポーリングの最小間隔)

承認フロー:ユーザーは verification_uri にアクセスし、user_code を入力してリクエストを承認します。その間、デバイスは device_code を使ってトークンエンドポイントをポーリングします。

ポーリング時のエラーコード:

エラー意味
authorization_pendingユーザーがまだ承認していません。ポーリングを続けてください
expired_tokenデバイスコードの有効期限が切れました。フローを最初からやり直してください
access_deniedユーザーが認可リクエストを拒否しました
Request device authorization
curl -X POST https://acme.authagonal.io/connect/deviceauthorization \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "client_id=my-cli" \
  -d "scope=openid profile email"

セッション終了/ログアウト

GET POST /connect/endsession

現在のユーザーセッションをサインアウトし、バックチャネルまたはフロントチャネルのログアウト URI が登録されているすべてのクライアントに通知して、そのセッションに紐付いたグラントを取り消します。現在のセッションと一致する id_token_hint がない場合は、まずユーザーにサインアウトの確認が求められます。

パラメーター必須説明
id_token_hint任意ID トークン。post_logout_redirect_uri の検証に使用されます
post_logout_redirect_uri任意ログアウト後のリダイレクト先(登録済みである必要があります)
state任意リダイレクト時に返される不透明な値

有効な post_logout_redirect_uri が指定され、登録済みの URI と一致する場合、ユーザーは 302 リダイレクトされます。それ以外の場合は、セッションが終了したことを示す JSON レスポンスが返されます。

バックチャネルログアウト

ユーザーがサインアウトすると、Authagonal は各クライアントの BackChannelLogoutUri に署名付き JWT を送信します。JWT には、sub、aud、iss、および http://schemas.openid.net/event/backchannel-logout イベントクレームが含まれます。この通知を受け取ったら、アプリケーションはユーザーのローカルセッションを無効にしてください。

SCIM 2.0 API リファレンス

Authagonal は、ユーザーとグループのプロビジョニングを自動化する SCIM 2.0 プロトコルに対応しています。Okta、Azure AD、OneLogin などの ID プロバイダーはこの API を使い、Authagonal テナントを社内ディレクトリと同期した状態に保てます。

ベース URL: https://{slug}.authagonal.io/scim/v2

認証: すべてのリクエストに Bearer トークンが必要です。SCIM トークンはポータルの SCIM ページで生成します。IdP がプロビジョニングする対象のクライアントを選択し、トークンを作成 をクリックします。

共通ヘッダー:

ヘッダー値
AuthorizationBearer SCIM_TOKEN
Content-Typeapplication/scim+json

一覧エンドポイントは、count(デフォルトは 100、最大 200。0 を指定すると合計件数のみを返します)と、filter パラメーターによる絞り込み(例:userName eq "[email protected]")を受け付けます。ユーザーは cursor でページングします。前のレスポンスの nextCursor を渡してください。グループは startIndex(1 始まり)または cursor のいずれかを受け付けます。

ユーザー

GET /scim/v2/Users: ユーザーを一覧表示します。ページネーションと絞り込みは任意です。

クエリパラメーター説明
startIndexユーザーでは 1 のみ受け付けます。代わりに cursor でページングしてください。それより大きい値を指定すると 400 invalidValue が返されます。
cursor不透明なページングカーソル:前のページの nextCursor を渡すと、次のページを取得できます
count1 ページあたりの最大件数(デフォルト:100、最大:200。0 を指定すると合計件数のみを返します)
filterSCIM フィルター式(例:userName eq "[email protected]")

GET /scim/v2/Users/{id}: Authagonal のユーザー ID を指定して、ユーザーを 1 件取得します。

POST /scim/v2/Users: 新しいユーザーを作成します。201 Created を返します。

フィールド必須説明
userNameはいメールアドレス(テナント内で一意であること)
name.givenNameいいえ名
name.familyNameいいえ姓
displayNameいいえフルネームの表示名
activeいいえユーザーが有効かどうか(既定:true)
externalIdいいえ上流の ID プロバイダーでの識別子

PUT /scim/v2/Users/{id}: ユーザーリソースを全体置換します。すべてのフィールドの指定が必要です。

PATCH /scim/v2/Users/{id}: SCIM PatchOp による部分更新です。

操作対応パス値の例
replaceuserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false、または文字列値
adduserName, active, name.givenName, name.familyName, displayName, externalId, preferredLanguagetrue / false、または文字列値
removename.givenName, name.familyName, displayName, externalId, preferredLanguage(値は不要)

DELETE /scim/v2/Users/{id}: ユーザーをソフト削除します(アカウントを無効化し、すべてのトークンを失効させます)。204 No Content を返します。

Create a user via SCIM
curl -X POST https://acme.authagonal.io/scim/v2/Users \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName": "[email protected]",
    "name": {
      "givenName": "Jane",
      "familyName": "Smith"
    },
    "displayName": "Jane Smith",
    "active": true,
    "externalId": "ext-12345"
  }'

グループ

GET /scim/v2/Groups: すべてのグループを一覧表示します。ページネーションと絞り込みは任意です。

GET /scim/v2/Groups/{id}: ID を指定して、メンバー一覧を含むグループを 1 件取得します。

POST /scim/v2/Groups: 新しいグループを作成します。201 Created を返します。

フィールド必須説明
displayNameはいグループの表示名
membersいいえメンバーオブジェクトの配列。各オブジェクトの value フィールドにユーザー ID を指定します
externalIdいいえ上流の ID プロバイダーでの識別子

PUT /scim/v2/Groups/{id}: グループリソースを(メンバー一覧を含めて)全体置換します。

PATCH /scim/v2/Groups/{id}: 部分更新:メンバーの追加、削除、置換、または displayName と externalId の変更を行います。

DELETE /scim/v2/Groups/{id}: グループを完全に削除(ハード削除)します。204 No Content を返します。

Add members to a group via PATCH
curl -X PATCH https://acme.authagonal.io/scim/v2/Groups/GROUP_ID \
  -H "Authorization: Bearer SCIM_TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
    "Operations": [
      {
        "op": "add",
        "path": "members",
        "value": [
          { "value": "USER_ID_1" },
          { "value": "USER_ID_2" }
        ]
      }
    ]
  }'

SCIM エラーレスポンス

SCIM リクエストが失敗すると、レスポンスボディは SCIM のエラースキーマに従います:{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "detail": "..." }。主なステータスコードは 400(不正なリクエスト)、404(リソースが見つからない)、409(競合/重複)、429(レート制限)です。

Portal API(自動化)

Portal API を使うと、ポータルでできることをすべて、マシン間(M2M)の認証情報で自社のバックエンドから自動化できます。ユーザー、クライアント、グループ、ロール、スコープ、SSO 接続、設定の管理が対象です。ポータル UI が呼び出しているのと同じ API です。

ベース URL: https://portal-api.<your-domain>/api/v1。リクエストは Bearer アクセストークンで認証します。テナントは URL ではなくトークンから決まります。

API 認証情報の作成

ポータルで クライアント → API 認証情報を作成 を開き、アクセスレベルを選んで名前を付けます。Authagonal が Portal API 用に構成された OAuth client_credentials クライアントを生成し、クライアント ID とシークレットを返します。

シークレットはすぐにコピー

クライアントシークレットが表示されるのは、作成直後の 一度だけ です。ダイアログを閉じる前にシークレットマネージャーに保存してください。紛失した場合は、その認証情報を削除して新しく作成してください。

アクセスレベル

スコープ付与される権限
tenant:ownerフルアクセス。テナント全体の削除など、オーナーのみが行える破壊的な操作も含みます。
tenant:adminオーナー専用の操作を除くすべてを管理できます。ユーザー、クライアント、SSO、グループ、ロール、ブランディング、設定が対象です。
tenant:developerクライアント、スコープ、ブランディング、プロビジョニングアプリを管理できます。
tenant:supportサポート業務のためにユーザーを閲覧・管理でき、監査ログも閲覧できます。

付与できるのは自分が持つ権限まで

認証情報には、それを作成する人を超える権限を与えられません。管理者はオーナースコープの認証情報を発行できず、プラットフォーム管理スコープはどの認証情報にも付与できません。

トークンの取得

テナントのトークンエンドポイント https://<your-tenant>.<your-domain>/connect/token で認証情報をアクセストークンと交換し、そのトークンを Bearer ヘッダーとして Portal API に送信します。トークンの有効期間は 1 時間です。

トークンを取得して API を呼び出す
# 1. Exchange the credential for an access token (your tenant's token endpoint)
curl -X POST https://acme.authagonal.io/connect/token \
  -d grant_type=client_credentials \
  -d client_id=api-3f2a... \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d scope=tenant:admin

# Response: { "access_token": "ey...", "token_type": "Bearer", "expires_in": 3600 }

# 2. Call the Portal API with the access token
curl https://portal-api.authagonal.io/api/v1/users \
  -H "Authorization: Bearer $ACCESS_TOKEN"

エンドポイント

パスはすべてベース URL からの相対パスで、Bearer アクセストークンが必要です。各グループの横に示すスコープは、そのグループに必要な認証情報の最小アクセスレベルです。ページングはリソースによって異なります。ユーザーと監査ログは count(1 から 200、デフォルトは 50)と after(前のレスポンスの continuationToken を指定)を受け付けます。グループは startIndex と count、組織は limit と cursor を受け付けます。クライアント、ロール、スコープはすべての行を返します。

クライアントtenant:developer

GET/api/v1/clientsOAuth クライアントを一覧表示します。

GET/api/v1/clients/{id}ID を指定してクライアントを 1 件取得します。

POST/api/v1/clientsクライアントを作成します。クライアントのレコードとともに 201 を返します。シークレットはここでは返されません。POST /api/v1/clients/{clientId}/secrets でシークレットを発行すると、一度だけ表示されます。

PUT/api/v1/clients/{id}クライアントを更新します(リダイレクト URI、グラントタイプ、トークンの有効期間、PKCE/PAR の要件)。

DELETE/api/v1/clients/{id}クライアントを削除します。

POST/api/v1/clients/api-credentialマシン間(M2M)の Portal API 認証情報を発行します。

ユーザーtenant:support

GET/api/v1/usersユーザーを一覧表示します。count、search(メールアドレス/名前の前方一致)、1 つの組織に絞り込む organizationId、カーソルページング用の after に対応しています。

GET/api/v1/users/countテナントのユーザー総数。

GET/api/v1/users/stats/mfaMFA の登録状況の統計。

GET/api/v1/users/{id}ユーザーを 1 件取得します。

POST/api/v1/users/inviteメールアドレスでユーザーを招待します。保留中のアカウントを作成し、招待されたユーザーが自分でパスワードを設定するためのリンクをメールで送信します。任意の organizationId と organizationRoles を指定すると、組織のメンバーシップも追加されます。

PUT/api/v1/users/{id}ユーザーを更新します(プロフィール、メールアドレス、isActive、emailConfirmed、organizationId)。メールアドレスまたは emailConfirmed を変更するには tenant:admin が必要です。

DELETE/api/v1/users/{id}ユーザーを削除します。

GET/api/v1/users/{id}/mfaGet a user's enrolled MFA methods.

DELETE/api/v1/users/{id}/mfaReset a user's MFA enrollment. Needs tenant:admin.

ロールtenant:admin

GET/api/v1/rolesロールを一覧表示します。

POST/api/v1/rolesロールを作成します。

DELETE/api/v1/roles/{id}ロールを削除します。

POST/api/v1/roles/assignユーザーにロールを割り当てます。

POST/api/v1/roles/unassignユーザーからロールを外します。

グループtenant:admin

GET/api/v1/groupsグループを一覧表示します。

GET/api/v1/groups/{id}メンバーを含めてグループを取得します。

POST/api/v1/groupsグループを作成します。

POST/api/v1/groups/{id}/membersグループにメンバーを追加します。

DELETE/api/v1/groups/{groupId}/members/{userId}グループからメンバーを削除します。

DELETE/api/v1/groups/{id}グループを削除します。

GET/api/v1/group-role-mappingsグループとロールのマッピングを一覧表示します(グループのメンバーシップに基づき、トークン発行時に付与されるロール)。

スコープtenant:developer

GET/api/v1/scopesAPI スコープを一覧表示します。

POST/api/v1/scopesスコープを作成します。

DELETE/api/v1/scopes/{name}スコープを削除します。

SSO 接続tenant:admin

GET/api/v1/saml/connectionsSAML 接続を一覧表示します。

POST/api/v1/saml/connectionsSAML 接続を作成します。

DELETE/api/v1/saml/connections/{id}SAML 接続を削除します。

GET/api/v1/oidc/connectionsOIDC 接続を一覧表示します。

POST/api/v1/oidc/connectionsOIDC 接続を作成します。

DELETE/api/v1/oidc/connections/{id}OIDC 接続を削除します。

GET/api/v1/sso/domainsSSO 接続にルーティングされるドメインを一覧表示します(ホームレルムディスカバリー)。

ブランディングtenant:developer

GET/api/v1/brandingテナントのブランディング(色、ロゴ、対応言語)を取得します。

PUT/api/v1/brandingテナントのブランディングを更新します。

設定tenant:admin

GET/api/v1/settingsテナント設定(ウェブフック、公開サインアップ、トークンポリシー)を取得します。

PUT/api/v1/settingsテナント設定を更新します。

POST/api/v1/settings/webhook-secret/regenerateウェブフックの署名シークレットをローテーションします。

POST/api/v1/settings/test-email現在のメール設定でテストメールを送信します。

カスタムドメインとメールtenant:admin

GET/api/v1/custom-domainsカスタムログインドメインとその検証状況を一覧表示します。

POST/api/v1/custom-domainsカスタムドメインを追加します。

POST/api/v1/custom-domains/{domain}/verifyカスタムドメインの DNS 検証を開始します。

DELETE/api/v1/custom-domains/{domain}カスタムドメインを削除します。

GET/api/v1/email/domains/{domainId}送信元メールドメインの DNS レコードと確認状態を取得します。

監査ログtenant:support

GET/api/v1/auditテナントの監査ログを照会します。

SCIM によるユーザーのプロビジョニング

IdP(Entra、Okta)からユーザーとグループを一括プロビジョニングする場合は、これらのエンドポイントではなく SCIM 2.0 API を使用してください。

例:ユーザーを招待する

POST /api/v1/users/invite
curl -X POST https://portal-api.authagonal.io/api/v1/users/invite \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "firstName": "Ada",
    "lastName": "Lovelace"
  }'

# 200 OK
# { "userId": "8f3a...", "email": "[email protected]" }

UI でできることはすべて可能

Portal API はポータル UI が使うのと同じエンドポイントを公開しているため、ポータルで実行できる操作はすべて自動化できます。ただし、認証情報のアクセスレベルの範囲内に限られます。

組織 API

以下のルートはすべて TenantAdmin ポリシーが必要で、特に記載がない限り /api/v1/organizations 配下にあります。認証情報の発行方法は Portal API を参照してください。2 つの一覧ルートはカーソルでページングします。limit(既定 50、1〜200)と、前回の nextCursor を cursor として渡してください。レスポンスは { items, nextCursor } で、不正なカーソルは 400 invalid_cursor になります。組織オブジェクトには読み取り専用の domains リストが含まれます。

メソッドパスボディ備考
GET/api/v1/organizations–組織の 1 ページ分を id 順で返します。クエリ:cursor?、limit?(既定 50、1〜200)。{ items, nextCursor } を返し、nextCursor が null なら最終ページです。
POST/api/v1/organizationsslug, name, brandingJson?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?201 と組織を返します。409 slug_taken。
GET/api/v1/organizations/{idOrSlug}–まず id で、次に slug で検索します。
PUT/api/v1/organizations/{id}name?, brandingJson?, slug?, enabled?, requireMembershipForTokens?, allowAutoMembership?, metadata?指定したフィールドだけが変更されます。異なる slug は拒否されます(作成後は変更できません)。domains はここでは変更できません。
DELETE/api/v1/organizations/{id}–まず組織のメンバーシップをすべて削除し、その後に組織自体を削除します。
GET/api/v1/organizations/{id}/members–メンバーシップの 1 ページ分をユーザー id 順で返します。メンバーの最新のメールアドレス/名前はユーザーストアから解決されます。クエリ:cursor?、limit?。
POST/api/v1/organizations/{id}/membersuserId? | email?, status?, roles?201 とメンバーシップを返します。404 user_not_found。409 membership_exists。予約済みの tenant:* および platform:* ロールは除去されるのではなく、400 invalid_role で拒否されます。
PUT/api/v1/organizations/{id}/members/{userId}status?, roles?status を active に設定すると、joinedAt がまだ設定されていない場合はその時点の日時が記録されます。
DELETE/api/v1/organizations/{id}/members/{userId}–ステータスを変更するのではなく、行そのものを削除します。
POST/api/v1/organizations/{id}/domainsdomainメールドメインを未検証の状態で登録します。201 と { domain, verified, verifiedAt, createdAt, recordName, recordValue } を返します。400 domain_invalid。409 domain_exists、domain_taken。
POST/api/v1/organizations/{id}/domains/{domain}/verify–recordName の TXT レコードを参照し、recordValue と完全一致するかを照合します。検証できればドメインとともに 200 を返します(再実行しても何も変わらず 200)。一致しなければ 409 verification_failed。ほかに 409 domain_taken、404 domain_not_found。
DELETE/api/v1/organizations/{id}/domains/{domain}–204。検証済みかどうかにかかわらず、ドメインの登録を取り消します。既存のメンバーはそのまま残ります。404 domain_not_found。
POST/api/v1/organizations/backfilldryRun? = true従来の AuthUser.organizationId タグを、実際の Organization/OrganizationMembership 行に移行します。
GET/api/v1/users/{userId}/organizations–このユーザーが所属するすべての組織と、各組織内でのステータス/ロール。

ログイン画面

テナントの認証サーバー上でエンドユーザーに表示される、ホスト型の画面です。Authagonal はすべての画面をすぐに使える状態で提供するため、UI を一切作らずに、完全で安全なサインイン体験を実現できます。このページでは各画面と、それを制御するポータル設定を紹介します。

完全なホワイトラベル

ここに挙げる画面はすべて、テナントの ブランディング 設定(ロゴ、色、アプリ名、カスタム CSS)で描画されます。また prefers-color-scheme にも従うため、ユーザーのデバイスに合わせてライトとダークが切り替わります。

サインイン

Hosted sign-in screen with an email field, Continue button, single sign-on provider buttons, and forgot-password and create-account links
  • メールアドレス先行の 2 ステップフロー:ユーザーがメールアドレスを入力して 続行 をクリックすると、パスワード欄が表示されます。
  • SSO 接続がある場合は、「{provider}で続行」 のシングルサインオンボタンが自動で表示されます。
  • パスワードをお忘れですか? と アカウントを作成 のリンク。どちらも表示・非表示を切り替えられます。
  • 自動化されたサインイン試行を抑止する Cloudflare Turnstile キャプチャ(任意)。

ポータル管理画面での設定

  • ブランディング で、ロゴ、色、アプリ名、サポート用メールアドレス、カスタム CSS を設定します。
  • パスワード再設定 と 登録 のリンクの表示・非表示(ブランディング)。
  • SSO 接続 を追加すると、ソーシャルサインインのボタンが加わります(SSO ページ)。
  • セッションの有効期間とロックアウトのしきい値(設定 → セッション)。

登録

Account registration screen with first and last name fields, email, password, and a live password-policy checklist
  • 姓名(任意)、メールアドレス、パスワード を入力してもらいます。
  • パスワードポリシーのチェックリスト が入力に合わせてリアルタイムに更新されるため、送信前に要件がわかります。
  • Cloudflare Turnstile キャプチャ(任意)。
  • すでにアカウントを持っているユーザー向けの 「サインイン」 リンク。

ポータル管理画面での設定

  • 登録 リンクの表示・非表示(ブランディング)。登録を完全に無効にするには、公開サインアップを許可 をオフにします(設定 → セッション)。
  • テナントの パスワードポリシー がチェックリストの内容を決めます。
  • ブランディング が画面全体のスタイルを決めます。

パスワードを忘れた場合

Forgot-password screen with an email field and a neutral check-your-email confirmation state
  • ユーザーがメールアドレスを入力すると、中立的な 「メールをご確認ください」 の確認が表示されます。
  • この画面は アカウントが存在するかどうかを決して明かさない ため、アカウント列挙の探りを防げます。
  • 「サインインに戻る」 リンクでサインイン画面に戻れます。

ポータル管理画面での設定

  • パスワード再設定 リンクの表示・非表示(ブランディング)。
  • テナントの メール配信 がリセット用メッセージを送信します。
  • ブランディング が画面全体のスタイルを決めます。

パスワードの再設定

Reset-password screen with new and confirm password fields and a live per-rule requirement checklist
  • 新しいパスワード と パスワードの確認 の欄に、ルールごとの要件をリアルタイムに示すチェックリスト が付きます。
  • リセットトークンが有効でなくなった場合は、リンクが無効または期限切れ であることをはっきり示します。
  • パスワードが変更されたことを確認する 完了表示。

ポータル管理画面での設定

  • テナントの パスワードポリシー がチェックリストの内容を決めます。
  • ブランディング が画面全体のスタイルを決めます。

MFA チャレンジ

MFA challenge screen with a method switcher, a six-digit authenticator code field, recovery-code entry, and a passkey button
  • 認証アプリ、パスキー、リカバリーコードを切り替える 方式スイッチャー。
  • すべての桁を入力すると自動送信される 6 桁の TOTP 入力欄。
  • 認証アプリを使えなくなったユーザー向けの リカバリーコード入力。
  • ハードウェアで裏付けられた検証のための パスキー ボタン。

ポータル管理画面での設定

  • MFA ポリシー はアプリケーションごとに設定します(クライアント → セキュリティ)。
  • 要素を登録済みのユーザーは、ポリシーにかかわらず 必ずチャレンジされます。

MFA セットアップ

MFA setup screen showing enrolled-method status, authenticator QR code and manual key, passkey enrolment, and recovery-code generation
  • 登録済みの方式 の状態を表示し、何がすでに設定済みかをユーザーが把握できるようにします。
  • QR コード、手動入力キーによる代替手段、確認ステップによる 認証アプリのセットアップ。
  • ハードウェアで裏付けられた認証のための パスキー登録。
  • アカウント復旧用の リカバリーコード生成。
  • MFA が必須ではなくセルフサービスの場合に使える、任意の スキップ。

ポータル管理画面での設定

  • MFA ポリシー はアプリケーションごとに設定します。必須 にするとログイン時にセットアップが強制されます(クライアント → セキュリティ)。
  • ブランディング が画面全体のスタイルを決めます。

デバイス認可

Device authorization screen with a centered user-code entry field, an Approve button, and an approved confirmation state
  • デバイスに表示されたコードを入力する、中央配置の ユーザーコード入力 欄。
  • デバイスを認可する 承認 ステップ。
  • ユーザーがまだ認証されていない場合の サインイン用の中間画面。
  • デバイスが認可された後の 承認完了の確認。

ポータル管理画面での設定

  • アプリケーションで デバイスコードグラント を有効にします(クライアント → スコープとグラント)。
  • デバイスコードの有効期間 を設定します(クライアント → トークン)。
Consent screen showing the requesting application's logo and name, a per-scope permission list, and Allow and Deny buttons
  • 要求元の クライアントのロゴと名前 を表示します。
  • 権限ごとにわかりやすいラベルを付けた スコープ別の一覧。
  • アクセスを許可または拒否する 許可 と 拒否 のボタン。
  • その判断が何を意味するかを説明する 同意に関する補足フッター。

ポータル管理画面での設定

  • アプリケーションごとに 同意を必須にする をオンにします(クライアント → 全般)。
  • ロゴ、名前、URL はアプリケーション自身のメタデータから取得されます。
  • ブランディング が同意カードを描画します。

連携アプリ(グラント)

Connected apps screen listing the applications a user has authorized with their scopes and granted date, plus a revoke control
  • ユーザーが認可したすべてのアプリを、名前、スコープ、許可日 とともに一覧表示します。
  • アプリへのアクセスを 取り消す ことができ、反映前に確認ステップがあります。
  • ユーザーがまだどのアプリも認可していない場合の、わかりやすい 空の状態 の表示。

ポータル管理画面での設定

  • 一覧には 同意が必須のアプリケーション が表示されます。
  • ブランディング が画面全体のスタイルを決めます。

アカウント

/login/account にあるホスト型のセルフサービスアカウントページです。サインイン済みのユーザーが自分のプロフィールと使用言語を管理でき、ポータルへのアクセスは不要です。

Self-service account screen with editable profile fields and a preferred Language selector
  • 姓名、会社名、電話番号 を編集できます。メールアドレスは読み取り専用で表示されます。
  • 対応ロケールから 使用言語 を選べます。選択は UI に即座にプレビューされ、保存すると保持されます。
  • 保存した言語は、そのユーザーのホスト型 UI と、受信するトランザクションメールの言語に使われます。

ポータル管理画面での設定

  • ブランディング が画面全体のスタイルを決めます。
  • 同じ使用言語は、管理者がポータルの ユーザー ページで編集することもできます。

認証フロー

認証フローは、エンドユーザーが Authagonal テナントとどうやり取りするか(ログイン、登録、パスワードの再設定、MFA のセットアップ)を扱います。これらのエンドポイントはホスト型ログインページが使用しており、独自のログイン UI を構築する場合は直接呼び出すこともできます。

ログイン

POST /api/auth/login

メールアドレスとパスワードでユーザーを認証します。成功するとセッション Cookie に署名し、ユーザープロフィールを返します。MFA が構成されている場合、セッションが完全に確立される前に第 2 要素が必要であることがレスポンスで示されます。

リクエストボディ:

Login request
{
  "email": "[email protected]",
  "password": "correct-horse-battery-staple"
}

成功レスポンス:

フィールド型説明
userIdstring一意のユーザー識別子
emailstringユーザーのメールアドレス
namestringフルネームの表示名
mfaAvailablebooleanユーザーが MFA 方式を登録済みかどうか

MFA 必須のレスポンス: ユーザーが MFA を登録済みの場合、レスポンスには mfaRequired: true と、challengeId、利用可能な MFA 方式を列挙した methods 配列が含まれます。

MFA セットアップ必須のレスポンス: アプリケーションの MFA ポリシーが「必須」なのにユーザーがまだ登録していない場合、レスポンスには mfaSetupRequired: true と、登録フロー用の setupToken が含まれます。

エラーレスポンス:

エラーコードHTTP ステータス説明
invalid_credentials401メールアドレスまたはパスワードが正しくありません
account_disabled403管理者によってアカウントが無効化されています
email_not_confirmed403ユーザーがメールアドレスを確認していません
locked_out423アカウントが一時的にロックされています(retryAfter を秒単位で含みます)。パスワードが正しい場合にのみ返されます。ロック中に誤ったパスワードを送信すると invalid_credentials が返されます
sso_required409メールドメインに SSO が構成されています(redirectUrl を含みます)
too_many_attempts429この IP から、またはこのメールアドレスに対するログイン試行が多すぎます。しばらくしてから再試行してください
captcha_failed400Turnstile のチャレンジに失敗したか、チャレンジがありません(Turnstile が有効な場合のみ)

SSO チェック: ユーザーのメールドメインに SSO 接続が構成されている場合、ログインエンドポイントは sso_required を redirectUrl とともに返します。クライアントはユーザーを SSO プロバイダーにリダイレクトしてください。

アカウントロックアウト: ログインに maxFailedAttempts 回連続で失敗すると、アカウントは lockoutDurationMinutes 分間ロックされます。どちらの値もテナント設定で変更できます。

ホスト型ログインページ

ログインエンドポイントは通常、アプリケーションから直接ではなく、ホスト型ログインページから呼び出されます。認証の開始には OIDC の認可コードフローを使用してください。ユーザーは自動的にホスト型ログインページへリダイレクトされます。

登録

POST /api/auth/register

新しいユーザーアカウントを作成し、確認メールを送信します。<strong>サインインにメール確認を必須にする</strong>(設定 &rarr; セッション)がオンの間は(これがデフォルトです)、ユーザーはメールアドレスを確認するまでログインできません。

リクエストボディ:

Registration request
{
  "email": "[email protected]",
  "password": "a-strong-password-here",
  "firstName": "Jane",
  "lastName": "Smith"
}
フィールド必須説明
emailはいメールアドレス(一意であること)
passwordはいテナントのパスワードポリシーを満たす必要があります
firstNameいいえ名
lastNameいいえ姓

成功: 新しいアカウントの userId とともに 201 Created を返します。すでに使われているメールアドレスで登録した場合も 201 を返します。メールアドレスが存在するかどうかは(アカウント列挙を防ぐため)決して開示せず、代わりに実際のアカウント所有者にメールで通知します。

エラーレスポンス:

エラーコードHTTP ステータス説明
weak_password400パスワードがテナントのパスワードポリシーを満たしていません
rate_limited429登録の試行回数が多すぎます
provisioning_rejected422プロビジョニング用ウェブフックが登録を拒否しました
invalid_email400メールアドレスが有効ではありません
captcha_failed400Turnstile のチャレンジに失敗したか、チャレンジがありません(Turnstile が有効な場合のみ)
public_signup_disabled403このテナントでは公開サインアップがオフになっています(設定 &rarr; セッション)

パスワードポリシー

送信前に GET /api/auth/password-policy でテナントのパスワード要件を確認してください。最小文字数と必要な文字種を含む rules リストが返されます。

パスワードの再設定

POST /api/auth/forgot-password

パスワード再設定メールを要求します。メールアドレスの列挙を防ぐため、このエンドポイントはメールアドレスが存在するかどうかにかかわらず、常に成功レスポンスを返します。

Forgot password request
{
  "email": "[email protected]"
}

POST /api/auth/reset-password

メールのリンクに含まれるトークンを使って、ユーザーのパスワードを再設定します。

Reset password request
{
  "token": "RESET_TOKEN_FROM_EMAIL",
  "newPassword": "new-strong-password"
}

パスワードの再設定に成功したときの副作用:

  • ログイン失敗回数のカウンターが 0 にリセットされます
  • 既存のリフレッシュトークンはすべて失効します
  • 新しいセキュリティスタンプが生成されます(既存のセッションはすべて無効になります)

MFA のセットアップと検証

Authagonal は 3 つの MFA 方式に対応しています:TOTP(認証アプリ)、WebAuthn(セキュリティキーと生体認証)、使い捨てのリカバリーコードです。

TOTP のセットアップ

POST /api/auth/mfa/totp/setup: <code>setupToken</code>、QR コードのデータ URI、手動入力キーを返します。ユーザーは認証アプリ(Google Authenticator、Authy、1Password など)で QR コードを読み取り、登録を確定します。

POST /api/auth/mfa/totp/confirm: セットアップで受け取った <code>setupToken</code> と認証アプリの 6 桁のコードを送信して、TOTP の登録を確定します。

Confirm TOTP enrollment
{
  "setupToken": "SETUP_TOKEN_FROM_SETUP_RESPONSE",
  "code": "123456"
}

WebAuthn のセットアップ

POST /api/auth/mfa/webauthn/setup:WebAuthn API 用の資格情報作成オプションを返します。ブラウザーはこのオプションを使って navigator.credentials.create() を呼び出します。

POST /api/auth/mfa/webauthn/confirm: ブラウザーからのアテステーションレスポンスを送信して、WebAuthn の登録を確定します。

リカバリーコード

POST /api/auth/mfa/recovery/generate: 10 文字(形式 <code>XXXXX-XXXXX</code>)の使い捨てリカバリーコードを 10 個生成します。各コードは、MFA を回避するためにちょうど 1 回だけ使用できます。事前に認証アプリまたはパスキーを登録しておく必要があります。

リカバリーコードは一度しか表示されません

リカバリーコードは生成時にのみ表示され、後から取得することはできません。ユーザーが認証デバイスとリカバリーコードの両方を失った場合、再びログインできるようにするには、管理者がポータルからそのユーザーの MFA 資格情報を手動で削除する必要があります。

MFA の検証

POST /api/auth/mfa/verify: パスワードによるログインに成功した後、MFA チャレンジを完了します。

フィールド必須説明
challengeIdはいログインレスポンスに含まれるチャレンジ ID
methodはい"totp"、"recovery"、"webauthn" のいずれか
codeTOTP / リカバリー6 桁の TOTP コード、またはリカバリーコード(XXXXX-XXXXX)
assertionWebAuthnnavigator.credentials.get() から返されたアサーションレスポンス

MFA の状態

GET /api/auth/mfa/status: ユーザーが現在登録している MFA 方式を返します。

SSO ログインフロー

Authagonal は SAML 2.0 と OIDC の両方の SSO 接続に対応しています。ドメインベースのルーティングにより、ユーザーのメールアドレスから使用すべき SSO プロバイダーが自動的に判定されます。

SSO チェック

GET /api/auth/[email protected]

フィールド型説明
ssoRequiredbooleanメールドメインで SSO が必須かどうか
providerTypestring"saml" または "oidc"
connectionIdstringSSO 接続の識別子
redirectUrlstringSSO ログインのためにユーザーをリダイレクトする URL

SAML フロー

ユーザーは GET /saml/{connectionId}/login にリダイレクトされ、そこから ID プロバイダーに SAML AuthnRequest が送信されます。IdP がユーザーを認証し、SAML レスポンスを Assertion Consumer Service(ACS)エンドポイントへ POST で返します。Authagonal はアサーションを検証し、ユーザーを作成または更新して、セッション Cookie に署名します。

IdP の設定に使う SAML メタデータは GET /saml/{connectionId}/metadata で取得できます。

OIDC フロー

ユーザーは GET /oidc/{connectionId}/login にリダイレクトされ、そこから PKCE を使って上流の ID プロバイダーへリダイレクトされます。ユーザーが認証すると、/oidc/callback のコールバックが認可コードを交換し、ID トークンを検証して、ユーザーを作成または更新します。

JIT プロビジョニング: SAML と OIDC のどちらのフローも、ジャストインタイムプロビジョニングに対応しています。これは各接続でデフォルトでオフです(JIT プロビジョニングを有効にする)。オンになっていて、ユーザーがテナントにまだ存在しない場合は、ID プロバイダーのクレームから自動的に作成されます。すでに存在する場合は、プロフィール属性がプロバイダーの最新の値に合わせて更新されます。

ドメインベースのルーティング

ドメインベースのルーティングにより、ユーザーは自分がどの SSO プロバイダーを使っているかを知る必要がありません。メールアドレスを入力するだけで、Authagonal がドメインを適切な SSO 接続に照合し、自動的にリダイレクトします。

Backend-for-Frontend(BFF)

BFF は OAuth トークンをブラウザから完全に排除します。シングルページアプリが保持するのは httpOnly のセッション Cookie だけで、自社バックエンド上のコンフィデンシャルクライアントが OpenID Connect フローを実行し、トークンをサーバー側で保持します。

シングルページアプリが読み取れるものは、クロスサイトスクリプティングで盗まれる可能性があります。メモリ上のアクセストークンも、localStorage 内のリフレッシュトークンも例外ではありません。また、トークンをブラウザに保存すると、その有効期間にも上限が生じます。スクリプトの届く場所にある長寿命のリフレッシュトークンは、常に抱え続けるリスクだからです。IETF のベストカレントプラクティス OAuth 2.0 for Browser-Based Apps は、まさにその理由でこのパターンを推奨しています。

その代わりに得られるのは、トークンを一切露出させずにページの再読み込み後も維持されるセッション、サーバー側で自動的に処理されるリフレッシュ、バックチャネルログアウトによる即時の失効、そしてブラウザが改ざんできたかもしれないトークンを API が解析しなくて済む認証済みプロキシです。

クライアントを作成する

ポータルでクライアントを開き、BFF アプリを作成を選択します。アプリの配信元であるアプリケーション URL(例:https://app.acme.com)を指定すると、自分で組み立てなくても、Authagonal が正しく設定されたコンフィデンシャルクライアントを登録します。リダイレクト URL とログアウト URL は、この1つの値から導出されます。

設定値
リダイレクト URI{appBaseUrl}/bff/callback
ログアウト後のリダイレクト URI{appBaseUrl}/
バックチャネルログアウト URI{appBaseUrl}/bff/backchannel-logout
グラントタイプauthorization_code, refresh_token
スコープopenid, profile, email, offline_access
PKCE とクライアントシークレットどちらも必須

シークレットは一度だけ表示される

レスポンスには clientId、clientSecret、authority が含まれます。保存されるのはハッシュだけなので、シークレットは後から取り戻せません。すぐにバックエンドの設定またはシークレットストアに保存してください。紛失した場合は、このクライアントの復旧を試みるのではなく、新しいクライアントを作成してください。

バックエンドに組み込む

2つのランタイムがサポートされ、同じコアプロトコルを共有しています。.NET 向けの Authagonal.Bff と Node 向けの @authagonal/bff で、後者には Express と Next.js 用のアダプターがあります。どちらにも、ポータルで受け取った値を設定します。Node パッケージには、Cookie の暗号化に使用する独自の cookieSecret も必要です。

.NET
// dotnet add package Authagonal.Bff
builder.Services.AddAuthagonalBff(o =>
{
    o.Authority    = "https://acme.authagonal.io";       // your tenant auth host
    o.ClientId     = builder.Configuration["Bff:ClientId"]!;
    o.ClientSecret = builder.Configuration["Bff:ClientSecret"]!;
    o.Scope        = ["openid", "profile", "email", "offline_access"];
    o.PostLogoutRedirectUri = "https://app.acme.com/";
});

// Trust X-Forwarded-Proto from your ingress. With no options, UseForwardedHeaders() changes nothing.
builder.Services.Configure<ForwardedHeadersOptions>(o =>
{
    o.ForwardedHeaders = ForwardedHeaders.XForwardedProto;
    o.KnownNetworks.Clear();
    o.KnownProxies.Clear();
});

var app = builder.Build();

app.UseForwardedHeaders();   // required behind a proxy or ingress, see the note below
app.MapAuthagonalBff();
app.MapFallbackToFile("index.html");   // your SPA
app.Run();
Node(Express)
// npm install @authagonal/bff
import express from 'express';
import { authagonalBff } from '@authagonal/bff/express';

const app = express();

app.use(authagonalBff({
  authority: 'https://acme.authagonal.io',
  clientId: process.env.BFF_CLIENT_ID,
  clientSecret: process.env.BFF_CLIENT_SECRET,
  cookieSecret: process.env.BFF_COOKIE_SECRET,   // encrypts the session and login cookies
  scope: ['openid', 'profile', 'email', 'offline_access'],
  postLogoutRedirectUri: 'https://app.acme.com/',
}));

app.listen(8080);

プロキシの背後では転送ヘッダーを信頼する

ほぼすべてのデプロイメントで、BFF は TLS を終端してプロセスとはプレーン HTTP で通信するイングレスやロードバランサーの背後に置かれます。転送ヘッダーを処理しないと、BFF はリクエストが安全でないと判断し、__Host- セッション Cookie を Secure 属性なしで発行し、ブラウザはそれを何も通知せずに破棄します。症状としては、ログインは問題なく完了するのに、セッションがいつまでも現れません。.NET では、上記のとおり ForwardedHeadersOptions で XForwardedProto を有効にし、app.UseForwardedHeaders() を MapAuthagonalBff() より前に呼び出します。オプションなしで呼び出すだけでは、どのヘッダーも信頼されません。Node のアダプターは X-Forwarded-Proto を自ら読み取り、__Host- Cookie には常に Secure を付けます。API に転送されるクライアントアドレスが実際のものになるよう、フレームワークの trust proxy 設定を行ってください。

エンドポイント

デフォルトでは /bff 配下にマウントされます。セッション Cookie は httpOnly かつ同一オリジンなので、これらはSPA と同じオリジンから配信する必要があります。別の API ドメインではなく、同じホスト名の背後に配置してください。

ルート用途
GET /bff/login?returnUrl=/ログインを開始し、Authagonal にリダイレクトします。完了後、ユーザーを returnUrl に戻します。
GET /bff/callbackOIDC のリダイレクト URI です。自動的に処理されるため、自分で実装することはありません。
GET /bff/userisAuthenticated、セッションのクレーム、sessionExpiresAt を返します。偽造防止ヘッダーが必要です。
GET|POST /bff/logoutローカルと Authagonal の両方でセッションを終了します。
POST /bff/backchannel-logoutAuthagonal からのログアウト通知を受け取ります。これにより、別の場所でサインアウトすると、このセッションも終了します。

ブラウザから

ナビゲーション以外のすべてのリクエストには、固定の偽造防止ヘッダーを付ける必要があります。これは Cookie の SameSite 属性と組み合わせてクロスサイトリクエストフォージェリを防ぎます。クロスサイトのフォーム送信ではカスタムヘッダーを設定できないため、このヘッダーのないリクエストは拒否されます。

サインイン中のユーザーを確認する
const me = await fetch('/bff/user', {
  headers: { 'X-Authagonal-Bff': '1' },
}).then(r => r.json());

if (!me.isAuthenticated) {
  // Navigate, do not fetch: this is a redirect to your identity provider.
  window.location.href = '/bff/login?returnUrl=' + encodeURIComponent(location.pathname);
}

ログインとログアウトは、fetch ではなくナビゲーションで行います:location.href = '/bff/login'。これらのルートは ID プロバイダーへのリダイレクトで応答しますが、リダイレクトチェーンは fetch では意味のある形でたどれません。

API を呼び出す

BFF は、API を自身のベースパス配下で転送し、その途中でセッションのアクセストークンを付与できます。ブラウザは Cookie を送信し、API は通常どおり検証するベアラートークンを受け取ります。そのトークンはページからは一切見えず、偽造もできません。アップストリームを登録すると、/bff/api/** へのリクエストが認証済みの状態でそこに届きます。リストを空のままにすると、プロキシは完全に無効になります。

アップストリーム API を転送する
o.Upstreams.Add(new BffUpstream
{
    Prefix        = "/orders",                        // matches /bff/api/orders/**
    TargetBaseUrl = "https://api.internal.acme.com",
    StripPrefix   = false,                            // keep /orders in the forwarded path
});
オプションデフォルト機能
Upstreams[]プロキシの転送先となる API。空の場合、プロキシエンドポイントは無効になります。
Prefix/このアップストリームが処理する、/bff/api 以降のパスプレフィックス(例:/orders)。
TargetBaseUrl-リクエストの転送先となるベース URL。
StripPrefixfalse転送前に、一致したプレフィックスを取り除きます。合成のルーティングプレフィックスを使い、パスの名前空間を共有する複数のバックエンドへ1つの BFF から振り分けられます。
AllowAnonymousProxyRequestsfalse利用可能なセッションのないリクエストを、拒否する代わりに Authorization ヘッダーなしで転送します。サインイン済みと匿名の両方の呼び出し元に応答する API 向けです。
RequiredAuthority[]type:action のペアで指定する権限ゲート(例:email:send)。設定すると、プロキシは転送前に、送信するトークンの RFC 9396 認可詳細を確認します。
AuthorityLocation-このアップストリームを識別する RFC 9396 の locations ルート。プロキシが呼び出す内部アドレスとは異なる公開リソース識別子に対して権限が付与されている場合に使います。
StrictAuthorityfalseプロキシが評価できないグラント制約を含む呼び出しを、転送せずに拒否します。プロキシは中身を判断せずに転送し、制約のコンテキストを導出しないため、デフォルトではオフです。
ExchangeRoutes[]アップストリームへの呼び出しに、セッションのプライマリアクセストークンではなく、コンテキストにバインドされた交換済みトークンを使うプロキシルート。最初に一致したパターンが優先されます。

WebSocket

WebSocket のハンドシェイクにはカスタムヘッダーもベアラートークンも載せられないため、偽造防止ヘッダーもプロキシも役に立ちません。チケットを有効にすると、SPA は GET /bff/ws-ticket を呼び出し、有効期間の短い使い捨てのチケットを接続 URL に付け、API 側でそれを引き換えられます。チケットは毎回、接続の直前に発行してください。初回の使用で削除され、数秒で期限切れになります。

オプションデフォルト機能
WsTicketsEnabledfalsews-ticket エンドポイントを有効にします。デフォルトはオフです。
WsTicketLifetime30sチケットの有効期間。URL に載せて送られるため、意図的に短くしています。
TicketExchangeParams[]チケットリクエストがトークン交換に転送できるクエリパラメーター。これにより、チケットはあらゆる用途に有効になるのではなく、そのコンテキストにバインドされます。

意図的にブラウザにトークンを渡す

BFF の要点はブラウザがトークンを保持しないことなので、この機能はオプトインで、範囲も限定されています。これは Cookie モデルでは対応できない唯一のケース、つまりベアラーで呼び出す必要がある別のオリジン上のリソースサーバー(iframe に埋め込むアプリなど)のための機能です。有効にすると、GET /bff/token?resource=… が交換済みトークンを返します。これはセッションのトークンを、許可リストにある1つのリソースにダウンスコープし、許可リストにあるコンテキストパラメーターにバインドしたものです。ブラウザがセッション自体のトークンを目にすることはなく、受け取るトークンは短寿命で、オーディエンスも1つだけです。許可リスト外のリソースを指定したリクエストは拒否され、これによって汎用のトークン発行手段になることを防いでいます。

オプションデフォルト機能
TokenEndpointEnabledfalsetoken エンドポイントを有効にします。デフォルトはオフです。
TokenEndpointResources[]トークンの宛先として指定できる resource の値。それ以外は拒否されます。
TokenEndpointExchangeParams[]コンテキストバインディングとして交換に転送されるクエリパラメーター(例:project_id)。

1つの BFF で複数のテナントに対応する

テナントのクエリパラメーターを設定すると、1つのデプロイメントで多数のテナントに対応できます。/bff/login?slug=acme がテナントを選択し、リゾルバーがそのテナントのオーソリティとクライアント資格情報を提供し、キーは相関 Cookie に載ってセッションへ引き継がれ、バックチャネルログアウトではトークンの発行者からテナントを解決します。デフォルトのリゾルバーは単一テナントの動作をバイト単位で同一に保つため、この機能を使わない限りコストは一切かかりません。

複数のインスタンスを実行する

セッションは IBffSessionStore の背後に保存され、そのデフォルトはプロセス内キャッシュです。単一インスタンスなら問題ありませんが、複数インスタンスでは誤りです。次のリクエストが別のレプリカに届いたユーザーはサインアウトされてしまいます。BFF を追加する前に、IDistributedCache 経由の Redis などの共有ストアを登録してください。

共有ストアだけでは不十分

レプリカ間のリフレッシュロックも必要です。リフレッシュのシングルフライトはプロセス内でしか効きませんが、セッションとそのローテーションするリフレッシュトークンは、すべてのレプリカが共有するストアに保存されています。2つのレプリカが同じセッションを読み取り、どちらもリフレッシュが必要と判断して、同じリフレッシュトークンを使用することがあります。これは盗まれたトークンのリプレイと区別がつかず、リプレイへの正しい対応はグラントファミリー全体の失効なので、ロックのない複数インスタンスの BFF では、ユーザーが日常的にサインアウトされかねません。 提供方法はどちらでも構いません。クラスタリング経由で ILeaseProvider を登録するか、セッションストアに IBffRefreshLockStore を実装します。後者は有効期限付きの条件付き書き込みで、すでに Redis を運用しているならこちらが近道です。ストアが共有されているように見えるのにロックがない BFF は、サポートチケットで発覚するまで放置せず、起動時に警告を出します。

知っておくべきオプション

全オプションの一覧です(.NET の表記)。Node パッケージはコアオプションを camelCase で受け付けるため、BasePath は basePath、SessionLifetime は sessionLifetimeSeconds となります。PersistentCookie、CorrelationLifetime(Node では 15 分に固定)、LoginPassthroughParams は .NET のみです。

オプションデフォルト機能
Authority-テナントの認証ホスト。OIDC メタデータはここから検出されます。リゾルバーが提供するマルチテナント構成の場合を除き、必須です。
ClientId-この BFF 用に登録されたコンフィデンシャルクライアントの ID。
ClientSecret-クライアントシークレット。BFF はコンフィデンシャルクライアントなので必須です。
Scopeopenid profile offline_access要求するスコープ。offline_access を含めないとリフレッシュトークンが発行されず、アクセストークンの期限切れとともにセッションが終了します。
BasePath/bffBFF のルートをマウントする場所。
CallbackPath/bff/callbackOIDC のリダイレクト URI のパス。クライアントの登録内容と一致している必要があります。
CookieName__Host-agbffセッション Cookie の名前。__Host- プレフィックスには HTTPS が必要なため、プレーン HTTP でのローカル開発では別の名前が必要です。
SessionLifetime8hセッションの最大有効期間。リフレッシュトークンの絶対有効期間に合わせてください。そうしないと、アイドル状態のユーザーが、まだ有効な資格情報を保持したままサインアウトされます。
PersistentCookiefalseブラウザを閉じても Cookie を維持するかどうか。どちらの場合も、リフレッシュトークンはサーバー側に保持されます。
CorrelationLifetime30mログインの開始からコールバックまでに許容される時間。state、nonce、PKCE verifier を運ぶ Cookie の有効期間を制限します。ログイン画面を開いたまま離れて、後で戻ってきたユーザーにも対応できる長さが必要です。
RefreshThresholdSeconds60アクセストークンを有効期限の何秒前にリフレッシュするか。
AntiForgeryHeaderX-Authagonal-Bffナビゲーション以外のリクエストでブラウザが送信しなければならないヘッダー名。
PostLogoutRedirectUri-ログアウト完了後にブラウザが移動する先。
ReturnUrlAllowlist[]相対パスでない returnUrl の対象として許可される絶対オリジン。相対パスは常に許可され、それ以外はすべて / に置き換えられるため、ログインルートを通じたオープンリダイレクトは起こりません。
LoginPassthroughParams[]/bff/login から authorize リクエストへ転送するクエリパラメーター。例えば prompt を転送すると、「はじめる」リンクをサインインではなく登録に振り分けられます。
TenantQueryParam-設定すると、1つの BFF で複数のテナントに対応します。上記を参照してください。

どちらのランタイムも同じ動作

.NET と Node のパッケージは同じコアプロトコル契約を実装しているため、ログイン、コールバック、ユーザー、ログアウト、バックチャネルログアウト、Cookie、偽造防止ヘッダー、リフレッシュの動作、基本的な上流プロキシは同一です。WebSocket チケット、トークンエンドポイント、交換ルート、StripPrefix、authority のゲート、匿名プロキシは .NET のみです。上記の名前は .NET の表記で、Node では対応する camelCase の名前を使います。

すべて差し替え可能

各部品はインターフェースなので、BFF をフォークせずに自社のインフラへ移せます。セッションの保存先には IBffSessionStore、Cookie の暗号化には ICookieProtector(デフォルトは ASP.NET Data Protection)、トークンエンドポイントおよび失効エンドポイントとの通信には ITokenClient を使います。また、IBffTenantResolver を使えば1つの BFF で複数のテナントに対応でき、ログイン時はクエリパラメーターからテナントを選択し、バックチャネルログアウト時はトークンの発行者からテナントを解決します。

AI アシスタントからポータルを操作する

AI アシスタントをテナントに接続すると、普段はクリックして行う作業を頼めるようになります。サインインできないユーザーを探す、そのユーザーにまだ第 2 要素が残っているかを確認する、誰かを招待する、管理者ロールを持っているのが誰かを調べる、といった作業です。

これは API キーではなく、通常の OAuth 接続です。各メンバーは本人としてサインインしてアクセスを承認するため、アシスタントはその人がポータルで実行できる操作だけを実行でき、それ以上のことはできません。漏洩しうるものは新たに作成されず、あるアシスタントを取り消しても他の人には一切影響しません。

有効化する

設定 を開き、AI アシスタントのアクセス を有効にします。有効にするまではオフのままで、オフの間はエンドポイントが単に拒否するのではなく、存在しない状態になります。有効にすると、AI クライアントに貼り付ける URL がパネルに表示されます。

MCP URL
https://portal-api.authagonal.io/api/v1/mcp/{your-tenant}

アシスタントが権限を得る仕組み

アシスタントはサインインを開始する前に自身を登録します。それを許可するのが、AI アシスタントのアクセスの有効化です。ほかに有効にする必要のあるものはありません。特に、このためにエンドユーザー向けテナントで動的クライアント登録を有効にするのは避けてください。その設定は自社のユーザーにサービスを提供するテナントを対象とするもので、アシスタントがサインインする場所ではありません。登録はアクセスではありません。新たに登録されたアシスタントは、メンバーの誰かがサインインして承認するまで一切の権限を持たず、その後もすべてのツールがその人のロールを毎回確認し直します。

アシスタントにできること

接続した本人ができることとまったく同じで、呼び出しのたびにその人自身のトークンに基づいて判定されます。tenant:support のエージェントには診断用ツールと日常業務用ツールが提供されます。管理者用ツールはそのエージェントから単に隠されているだけではなく、名前を直接指定しても拒否されます。ポータル内で制限されている操作はここでも制限されたままです。ユーザーのメールアドレスの変更にはポータルで管理者ロールが必要であり、ここでも同様に必要です。

通常のグラントなので、管理も通常の方法で行えます。アカウントの 承認済みアプリ ページでアシスタントを削除するとリフレッシュできなくなり、現在のアクセストークンの有効期限が切れた時点で動作しなくなります。アシスタントが行った変更はすべて、代理で操作した本人の操作として監査ログに記録されるため、確認する記録はいつも読んでいるものと同じです。

ツール

このリリースには33個のツールがあります。どのツールを有効にするかは AI クライアント側で決めるため、読み取りだけをさせたい場合は読み取り用ツールだけをアシスタントに渡すこともできます。

ツールロール機能
find_userサポートメールアドレス、名前の先頭部分、または ID でユーザーを検索します。他のすべての操作の出発点です。
get_userサポート1 人のユーザーの全情報を取得します。有効かどうか、確認済みかどうか、ロックアウトされているかどうかも含まれます。
get_user_mfaサポートユーザーが登録している第 2 要素を取得します。
get_user_sessionsサポートユーザーが現在どこでサインインしているかを取得します。
search_auditサポート実行者、アクション、または操作対象で監査ログを検索します。
list_usersサポートディレクトリを一覧表示します。必要に応じて 1 つの組織に絞り込めます。
get_user_statsサポートユーザー数と、そのうち第 2 要素を使っている人数を取得します。
invite_userサポートメールアドレスで誰かを招待します。
resend_inviteサポート招待を再送します。
send_verification_emailサポートメールアドレス確認メッセージを再送します。
update_userサポートプロファイルを更新します。メールアドレスの変更には引き続き管理者権限が必要です。
revoke_user_sessionsサポートユーザーをすべての場所からサインアウトさせます。
list_roles管理者テナントで定義されているロールを取得します。
list_role_members管理者特定のロールを持っているユーザーを取得します。
assign_role管理者ユーザーにロールを付与します。
unassign_role管理者ロールを外します。
reset_user_mfa管理者認証アプリを紛失したユーザーのために、すべての第 2 要素を削除します。
get_settings管理者テナントの設定を取得します。
list_sso_connections管理者SSO 接続と、それぞれが対象とするドメインを取得します。
list_organizations管理者テナント内の組織を 1 ページずつ取得します。
get_organization管理者ID またはスラッグで 1 つの組織をメールドメインとともに取得します。
create_organization管理者組織を作成します。スラッグは変更できません。
update_organization管理者組織の名前、ポリシーフラグ、メタデータ、またはブランディングを変更します。スラッグは変更できません。
delete_organization管理者組織とそのすべてのメンバーシップを削除します。
list_organization_members管理者組織のメンバーを 1 ページずつ取得します。
add_organization_member管理者ユーザーを組織に追加します。
update_organization_member管理者組織内でのメンバーのステータスまたはロールを変更します。
remove_organization_member管理者ユーザーを組織から削除します。
add_organization_domain管理者組織のメールドメインを申請します。公開すべき DNS TXT レコードが返されます。
verify_organization_domain管理者TXT レコードを確認し、ドメインを検証済みにします。繰り返し実行しても安全です。
remove_organization_domain管理者ドメインの申請を取り下げます。既存のメンバーはそのまま残ります。
list_user_organizations管理者ユーザーが所属する組織を、各組織でのステータスとロールとともに取得します。
list_clients開発者テナントに登録されている OAuth クライアントを取得します。

読み取りと書き込みは明示されています

各ツールは、読み取りだけを行うのか、何かを変更するのか、その変更が破壊的なのかをクライアントに伝えます。優れたクライアントはこの情報を使い、検索は確認なしで実行し、第 2 要素の削除のような操作の前では一時停止します。ただし、これは利便性のための仕組みであり、制御の仕組みではありません。アシスタントに何を許可するかを実際に決めるのは、呼び出しのたびに確認されるあなた自身のロールです。

まだ含まれていないもの

ユーザーの削除、SSO 接続の作成や編集、請求、バックアップ、クライアントシークレットは、いずれもこのリリースには含まれていません。削除は消去キューの横ではなく、消去キューの中で扱うべきものです。SSO 接続は規模が大きく、編集を誤ると従業員全員がロックアウトされかねないため、当面は読み取り専用です。また、クライアントシークレットを返すツールがあると、シークレットがアシスタントのトランスクリプトに残ってしまいます。これらのうちどれが必要か、どの順番で欲しいかをお知らせください。

MCP サーバーの認証

Model Context Protocol サーバーを公開している場合、Authagonal をその背後の認可サーバーにできます。AI アシスタントが接続すると、その利用者がサインインしてアクセスを許可し、お客様のサーバーは他の API と同じように検証できる通常のベアラートークンを受け取ります。

代わりの方法はアシスタントの設定に API キーを貼り付けることですが、これは背後にユーザーがおらず、有効期限も同意の手順もなく、全員分をローテーションせずに1つのコネクターだけを取り消す方法もない資格情報です。OAuth で行えば、グラントは特定の個人に属し、監査ログで確認でき、他に一切影響を与えずにポータルから取り消せます。

接続の流れ

やり取り全体がディスカバリーによって進むため、仕様に準拠したクライアントには、お客様のサーバーの URL 以外の設定は不要です。

ステップ処理内容
1コネクターがトークンなしで MCP サーバーを呼び出し、参照先を示す 401 を受け取ります。
2保護リソースのメタデータを取得します。そこには、お客様の Authagonal テナントが認可サーバーとして記載されています。
3テナントの認可サーバーメタデータを取得し、まだどこにも登録されていないため、自身を登録します。
4ユーザーをサインインさせてアクセスを承認してもらいます。その際、トークンを求めるリソースとして MCP サーバーを指定します。
5得られたベアラートークンを使ってサーバーを再度呼び出します。このトークンはそのサーバーとそのユーザーにスコープされています。

この流れに Authagonal 固有のものは何もありません。MCP の認可仕様そのもので、リソースメタデータには RFC 9728、認可サーバーの検出には RFC 8414、登録には RFC 7591、リソースの指定には RFC 8707 を使っています。仕様に従うコネクターなら、当社向けの特別な対応なしで動作します。

コネクターに自身を登録させる

面識のないコネクターは手動で作成したクライアントを使えないため、実行時にクライアントを登録します。これはデフォルトではオフです。設定で動的クライアント登録をオンにすると、登録エンドポイントがディスカバリードキュメントに表示されます。オフのままならエンドポイントは公開されず、リクエストを拒否します。有効にしても、登録が開かれるのはお客様のテナントだけで、他のテナントでは決して開かれません。

ガード処理内容
グラントタイプ登録できるのは認可コードフローとリフレッシュフローだけです。自己登録で、ユーザーを完全に迂回するマシン間クライアントを作成することはできません。
PKCE登録時の要求内容にかかわらず、登録されたすべてのクライアントで強制されます。
同意これも強制されます。登録されたコネクターは、要求内容を人が確認して承認するまでトークンを取得できません。
スコープOIDC の組み込みスコープは常に利用できます。それ以外に自己登録するクライアントが要求できるのは mcp という名前のスコープだけで、それもテナントがそのスコープをロール制限なしで定義している場合に限られます。roles と groups は自己登録では要求できません。
レート制限登録は IP アドレスごとに1時間あたり10件までです。そのため、公開されたエンドポイントを使ってクライアントストアを埋め尽くすことはできません。

両方のディスカバリーパスに対応

MCP クライアントは /.well-known/oauth-authorization-server(RFC 8414)を通じて認可サーバーを解決し、OIDC クライアントは /.well-known/openid-configuration を使います。テナントは両方に同じメタデータで応答するため、MCP 仕様に従うコネクターは、参照先を教えられなくてもお客様のテナントを見つけられます。

MCP サーバーが実装するもの

必要なのは小さなことが2つだけで、それ以外は通常のリソースサーバーです。1つ目は、お客様のテナントを認可サーバーとして記載した保護リソースメタデータを公開することです。これを well-known パスで配信し、MCP エンドポイントがサブパスにある場合は、パスを末尾に付けた形式でも配信してください。クライアントは両方を試すからです。

保護リソースのメタデータ
GET https://your-app.example/.well-known/oauth-protected-resource

{
  "resource": "https://your-app.example/mcp",
  "authorization_servers": ["https://acme.authagonal.io"],
  "bearer_methods_supported": ["header"],
  "scopes_supported": ["mcp"]
}

2つ目は、有効なトークンのない呼び出しが届いたときに 401 で応答し、そのメタデータを指す WWW-Authenticate ヘッダーを付けることです。このヘッダーこそが拒否を接続に変えます。これがないと、クライアントは認証先を知る手段がなく、ただ失敗します。

トークンを検証する
// Validate the connector's token like any other resource server.
builder.Services.AddAuthentication().AddJwtBearer("McpBearer", o =>
{
    o.Authority = "https://acme.authagonal.io";              // your tenant
    o.TokenValidationParameters.ValidAudience = "https://your-app.example/mcp";
});

// Unauthenticated? Point the connector at the metadata rather than just refusing.
http.Response.Headers.WWWAuthenticate =
    "Bearer resource_metadata=\"https://your-app.example/.well-known/oauth-protected-resource\"";
return Results.Unauthorized();

署名だけでなくオーディエンスも確認する

トークンがお客様のサーバー向けに発行されたことを検証してください。コネクターは MCP サーバーをリソースとして指定するため、トークンのオーディエンスはお客様のリソース URL になります。署名と発行者だけを確認するリソースサーバーは、同じテナント内の別のリソース向けに発行されたトークンも受け入れてしまいます。これが、あるコネクターのアクセスが別のコネクターのアクセスになってしまう原因です。

スコープ、プラン、失効

スコープページで mcp という名前のスコープをロール制限なしで定義すると、自己登録するコネクターがそれを要求できるようになります。このスコープは同意画面に表示され、ユーザーは何を承認するのかを確認できます。トークンのサブジェクトはサインインした本人なので、サーバーはすべてのコネクターを同じように扱うのではなく、この特定の人物に何を許可するかを判断できます。自己登録したコネクターは roles や groups スコープを要求できないため、これらがトークンに含まれることを期待せず、サーバー側で参照してください。

通常の OAuth グラントなので、失効も通常どおり機能します。ユーザーがアカウントの 承認済みアプリ ページでコネクターを削除すると、そのグラントとリフレッシュトークンが破棄され、更新できなくなります。既存のアクセストークンは /connect/introspect と /connect/userinfo によって直ちに拒否されますが、JWT をローカルで検証するだけのサーバーは有効期限が切れるまでそれを受け入れます。監査ログには、各サインインが対象のクライアントとともに記録されます。

設定処理内容
Dynamic client registrationコネクターによる自己登録を許可するポータル設定。デフォルトはオフです。
mcp自己登録するクライアントが要求できる、OIDC の組み込み以外の唯一のスコープ。提供するには、テナントでロール制限なしで定義します。
resourceコネクターが MCP サーバーを指定するために送信するパラメーター。トークンのオーディエンスをそのサーバーに絞り込みます。

独自のログイン UI を構築する

Authagonal がホストするログイン、登録、パスワード再設定、MFA の画面を独自の UI に置き換えられます。認証、MFA、SSO、セッション、トークン発行は引き続き Authagonal が担います。方法は 2 つあります。React コンポーネントライブラリを使うか、任意のフレームワークから認証 API を直接呼び出すかです。この機能はオプトインです。まず 設定 → セッション で カスタムログイン UI を有効にしてください。

A fully customized hosted login page with a tenant logo, brand color, and support email in the footer

前提条件:ルートドメイン上のカスタムドメイン

ログインセッションはファーストパーティ Cookie なので、UI と Authagonal の認証サーバーは同じ登録可能ドメインを共有する必要があります。アプリが動いているのと同じルートドメインで、カスタム認証ドメインを Authagonal に向けてください。例:認証は login.acme.com、アプリは app.acme.com。有効なカスタムドメインが存在するまで、カスタムログイン UI の設定は無効のままです。

自社の UI認証ホスト動作
app.acme.comlogin.acme.com✅ 同じルート
acme.comauth.acme.com✅ 同じルート
app.acme.comacme.authagonal.io❌ クロスサイト
myapp.iologin.acme.com❌ クロスサイト

カスタムドメインが必要な理由

クロスサイトのセッション Cookie はサードパーティ Cookie になり、ブラウザー(Safari、Chrome)はこれを段階的に廃止しつつあります。認証を自社のルートドメインに置けば Cookie はファーストパーティになり、将来も安心です。プラットフォームもこれを強制しています。クロスオリジンの認証呼び出しは、認証ホストと同じルートドメインを共有するオリジンからのものしか受け付けません。

/api/auth の呼び出しには、クライアントの CORS 設定は不要です。カスタムログイン UI をオンにすると、認証ドメインと同じ登録可能ドメイン上のすべてのオリジンが自動的に許可されます。UI のオリジン(例:https://app.acme.com)をクライアントの 許可する CORS オリジン(クライアント → URI)に追加する必要があるのは、ブラウザがトークン交換も行う場合だけです。

React:@authagonal/login

npm i @authagonal/login は、認証ロジックと UI を 1 つのパッケージで提供します。Authagonal のホスト型ログイン自体もこのパッケージで構築されています。使い方の粒度を選んでください:

  • アプリ全体:App を組み込み、ブランディングでテーマを設定します。
  • ページを組み合わせる:LoginPage、MfaChallengePage、ResetPasswordPage などを独自のレイアウト内で使います。
  • プリミティブとロジック:AuthLayout/Button/Input と API クライアント(login、mfaVerify、forgotPassword など)で独自の画面を構築します。
@authagonal/login API を使った独自画面
import { AuthLayout, Input, Button, login, ApiRequestError } from '@authagonal/login';

// returnUrl: the /connect/authorize URL your login page was opened with
function MyLogin({ returnUrl }: { returnUrl: string }) {
  async function onSubmit(email: string, password: string) {
    try {
      const res = await login(email, password, returnUrl);  // POST /api/auth/login (sets the session cookie)
      if (res.mfaRequired) {/* render your MFA step, then mfaVerify(res.challengeId!, 'totp', code) */}
      else if (res.mfaSetupRequired) {/* enrol first: mfaTotpSetup(res.setupToken) */}
      else window.location.href = returnUrl;                 // resume /connect/authorize
    } catch (e) {
      if (e instanceof ApiRequestError) {/* show e.message; e.error is the error code */}
    }
  }
  return <AuthLayout>{/* your own markup + <Input/> <Button/> */}</AuthLayout>;
}

任意のフレームワーク:認証 API を呼び出す

React を使っていない場合は、認証フローのエンドポイント(/api/auth 配下)を直接呼び出し、その後で標準の OIDC /connect/authorize フローに引き渡します。セッション Cookie が保存されるよう、credentials: 'include' を送信してください。

エンドポイント用途
POST /api/auth/login認証します。mfaRequired または戻り先 URL を返します
POST /api/auth/registerセルフサービス登録(有効な場合)
POST /api/auth/forgot-passwordパスワード再設定を開始
POST /api/auth/reset-passwordパスワード再設定を完了
GET /api/auth/password-policyパスワードポリシー(ルールの表示用)
POST /api/auth/mfa/*MFA のセットアップと検証(TOTP、WebAuthn、リカバリー)

credentials: 'include' を使用する

セッションは Cookie なので、fetch では資格情報を送信する必要があります。クロスオリジンの呼び出しが成功するのは、カスタムログイン UI が有効で、かつオリジンが認証ホストと同じルートドメインを共有している場合だけです。それ以外は 403 で拒否されます。
認証してから OIDC に引き渡す
# 1. Authenticate (browser fetch; credentials:'include' so the session cookie is stored)
curl -i -X POST https://login.acme.com/api/auth/login \
  -H "Content-Type: application/json" \
  -H "Origin: https://app.acme.com" \
  --data '{"email":"[email protected]","password":"..."}'
# (handle {"mfaRequired":true} → POST /api/auth/mfa/verify, then continue)

# 2. Hand off to the OAuth flow: top-level navigation to the authorize endpoint with PKCE:
# https://login.acme.com/connect/authorize?client_id=my-app&redirect_uri=...&response_type=code
#   &scope=openid%20profile%20email&code_challenge=...&code_challenge_method=S256
# The session cookie (same-site) authenticates the user; you get back a code → exchange at /connect/token.

1つのテナント、多数の顧客

1社のインテグレーター、1つのテナントで、それぞれ独自のログインドメインと独自のユーザーを持つ N 社のブランド付き顧客を、顧客ごとにテナントを作らずに扱うためのパターンです。宣言的プロビジョニングと組織は、これをエンジニアリング作業ではなく設定変更で済ませるために存在します。

構成

  • 顧客ごとに1つの組織を、単一のテナント内に作成します。
  • 顧客ごとに1つのブランド付きログインドメインを用意し、それぞれをその顧客の組織に固定します。そのドメインでサインインしても、その組織向けのトークンしか発行されません。
  • アプリケーションも顧客ごとのホストで配信しますが、すべて同じデプロイメントからです。コード、ビルド、イメージのいずれも顧客間で違いはありません。
  • リライングパーティーは、ビルド時の定数ではなく、自身が動作しているホストからオーソリティを選びます。同じバンドルが、どの顧客ホストから配信されたかに応じて、異なるログインドメインに自らを接続します。

手順

顧客をプロビジョニングします。新しい組織とそのドメインを指定したスペックで宣言的プロビジョニングエンドポイントを呼び出します。この呼び出しは冪等で、セクション単位で適用されます。

プロビジョニングのスペック
{
  "organizations": [
    { "slug": "acme", "name": "Acme Pty Ltd" }
  ],
  "customDomains": [
    { "domain": "login.acme.example", "organizationSlug": "acme" }
  ]
}

顧客の DNS をテナントに向けます。顧客自身のゾーンに CNAME を1つ設定するだけで、管理権限と意図の両方を証明できます。TXT トークンは不要です。

CNAME record
_authagonal-challenge.login.acme.example.  CNAME  <slug>.<platformDomain>.

プラットフォームと同じ Cloudflare アカウントの場合

レコードは DNS のみ(プロキシなし)にする必要があります。同じアカウント内の2つのゾーン間でプロキシされた CNAME は、プラットフォームの SaaS カスタムホスト名に決して到達しません。別のアカウントにある顧客ゾーンには、そもそも誤設定しうるプロキシの切り替えがありません。

アプリケーションを顧客のホストに向けます。リライングパーティーは、現在配信しているホストに基づいて、リクエストごとに自身の OIDC オーソリティを解決します。顧客マップにエントリがないホストは従来の単一テナントの導出方法にフォールバックするため、顧客の追加は既存に影響しない純粋な追加になります。

oidc.ts
export function resolveCustomer(): { authority: string; clientId: string } {
  const cfg = getConfig();
  const customer = cfg.customers?.[window.location.host];
  if (customer) return customer;
  const baseDomain = cfg.baseDomain || window.location.hostname.replace(/^consumer\./, '');
  return { authority: `https://${cfg.tenantSlug}.${baseDomain}`, clientId: cfg.clientId };
}

クライアントは組織固有のものを何も要求しません。organization パラメーターも、顧客ごとのスコープもありません。組織の選択はドメインの固定によって完全にサーバー側で行われます。だからこそ「アプリはすべての顧客で同じコード」が実際に成り立ちます。

顧客に表示される内容

ログインページは、テナントのブランディングに各組織独自のブランディングを重ねて表示します。ブランディングの上書きを参照してください。各顧客は、他の顧客に影響を与えることなく、独自のアプリ名、ロゴ、色、サポートメールを持てます。

顧客 A のユーザーが顧客 B のホストでサインインしようとすると、顧客 B のデータが表示されるのではなく、拒否されます。競合がどのように生じたかに応じて、拒否は次の2つの形のいずれかになります。

  • リライングパーティーは何も送らず、固定されたドメインにアクセスするだけです。固定がユーザーに代わって組織を指定するため選択は明示的になり、B のメンバーシップを持たない顧客 A のユーザーは、トークンが発行される時点で拒否されます。
  • リライングパーティー自身が別の組織を指定する場合です。ログインページが表示される前に、ドメイン固定ミドルウェアによって 400 で直接拒否されます。

メンバーシップによる拒否はアプリにリダイレクトされる

上記の1つ目の形は、壊れたログインページではありません。リライングパーティー自身の redirect_uri への通常の error=access_denied OIDC リダイレクトであり、どの組織のメンバーシップが欠けていたかを正確に示す説明が付きます。

N+1 社目の顧客のオンボーディング

Terraform でプロビジョニングの呼び出しを行っていれば、次の顧客のオンボーディングは1つのファイルの編集で済みます。organizations 配列にエントリを1つ、それを固定するドメインエントリを1つ、DNS レコードを1つ追加するだけです。アプリケーション、そのデプロイメント、ビルドは一切変わりません。ホストベースのリゾルバーは、設定エントリが存在した瞬間に新しい顧客を認識します。

リファレンス実装

永続的な開発用テナントが、2つの実在する顧客ドメインに対してこのパターン全体をエンドツーエンドで実行しています。そのエンドツーエンドテストスイートは、メンバーをプロビジョニングし、ブランディングと org_id クレームを確認し、上記の2つの拒否の形をどちらも検証します。単なる説明ではなく、実行可能なドキュメントです。

ローカルで実行する
cd e2e-consumer && DOMAIN=authagonal.dev npx playwright test organizations-domains

このスイートは他のすべてのスペックと同様にデフォルトで実行されます。リポジトリ自体の管理外にあるインフラに依存する唯一のスペックであるため、リファレンスドメインがプロビジョニングされていない環境ではスキップできます。

プランと上限

Authagonal には Free プランと 4 つの有料プランがあります。すべてのプランにすべての認証機能が含まれています。プランの違いは月間アクティブユーザー(MAU)の上限と超過料金です。また、Free プランはコミュニティサポートのみで、テナントサポートデスクは含まれません。

プラン一覧

プランMAU 上限超過超過料金/ユーザー
Free250いいえ-
Starter1,000いいえ-
Pro5,000はい$0.04/ユーザー
Scale25,000はい$0.025/ユーザー
Enterprise100,000はい$0.015/ユーザー

月間アクティブユーザー(MAU)

月間アクティブユーザーとは、暦月(UTC)の間に少なくとも 1 回認証に成功した一意のユーザーです。SCIM でプロビジョニングされていても、ログインしていないユーザーは MAU の合計にカウントされません。

超過:プランが超過に対応しており(Pro 以上)、テナントで超過が有効になっている場合(デフォルトではオフ)、MAU の上限を超えたユーザーには、上のプラン表に記載されたユーザー単価で請求されます。超過の上限は、上限を超えて許可する追加ユーザーの最大数を設定するものです。

適用:プランが超過に対応していない場合(Free、Starter)、または超過が有効になっていない場合、今月すでにサインインしたユーザーは常にアクセスを維持できます。テナントが初めて上限を超えると 10 日間の猶予期間が始まり、その間は新しいユーザーもサインインできます。猶予期間が過ぎると、今月まだサインインしていないユーザーは、翌月になるかアップグレードするまで拒否されます。

すべてのプランで全機能を利用可能

すべてのプランに全機能が含まれます:SSO、SCIM、MFA、カスタムドメイン、ブランディング、ウェブフック、監査ログ、ポータル。