本記事は元々 blog.logto.io に掲載されたものです。
マジックリンクとは?
マジックリンクは、ユーザーがメール(またはSMS)で一度きりのログインURLを受け取り、クリックするとパスワードを必要とせずにログインできるパスワードレス認証方法です。
マジックリンクの主なセキュリティ機能は次のとおりです:
- 一度限りのトークン: クリック後、再利用を防ぐためにトークンは無効になります。
- リンクの有効期限: マジックリンクには短い有効期限(例:10分)を設定する必要があります。
- レート制限: 特定の時間枠内に送信できるマジックリンクの数を制限して悪用を防ぐ。
- デバイス/ブラウザの結合(オプション): リンクの使用を元のデバイスまたはIPに制限して傍受を防ぐ。
マジックリンクの構成
マジックリンクは次のように構成されます:
- URLルート: アプリのランディングページを指します。
- 一度限りのトークン: パスワードレス認証に使用される一意で一度きりの消費トークン。
- ユーザーのメール: トークンの真正性とユーザーの身元を確認するために使用されます。
- 追加のパラメータ: アプリのニーズに応じてオプション。
例として、マジックリンクは次のようになります:
https://yourapp.com/landing-page?one_time_token=Cfmtev6HFEA4vmLpmDeAXvvtiWyQXXLu&email=johndoe@example.com
マジックリンクを作成するには、一度限りのトークンを生成し、それをユーザーに安全に送信し、リンクをクリックしたときにそれを検証する必要があります。
マジックリンクのワークフロー
- ユーザーがマジックリンクをリクエスト: アプリでメールアドレスを入力します。
- 一度限りのトークン生成: サーバーはトークンを生成し、それをリンクとしてメールで送信します。
- ユーザーがリンクをクリック: ユーザーはメールのリンクをクリックします。
- トークンの検証: サーバーはトークンが有効かどうかを確認します。
- ユーザーが認証された: トークンが有効であれば、ユーザーはログインされます。
Logtoでのマジックリンクの実装方法
ステップ1: 一度限りのトークンをリクエスト
Logto Management API を使用して一度限りのトークンを作成します。
POST /api/one-time-tokens
サンプルリクエストボディペイロード:
{
"email": "user@example.com",
"expiresIn": 3600,// オプション。デフォルトは600(10分)。
"context": {
"jitOrganizationIds": ["abcdefgh1234"]// オプション。ユーザーは指定された組織にプロビジョニングされます。
}
}
ステップ2: マジックリンクを作成
一度限りのトークンを取得したら、エンドユーザーのメールアドレスにマジックリンクを送ることができます。マジックリンクには少なくともトークンとユーザーのメールをパラメータとして含め、あなたのアプリケーションのランディングページに移動する必要があります。例:https://yourapp.com/landing-page
。
マジックリンクの単純な例として、次のようになります:
https://yourapp.com/landing-page?token=YHwbXSXxQfL02IoxFqr1hGvkB13uTqcd&email=user@example.com
注意:
マジックリンクのパラメータ名は完全にカスタマイズ可能です。アプリケーションの要件に基づいて追加情報を加えることができ、すべてのURLパラメータをエンコードすることができます。
ステップ3: Logto SDKを介した認証フローのトリガー
エンドユーザーがマジックリンクをクリックしてあなたのアプリケーションに移動した後、token
およびemail
パラメータをURLから抽出し、Logto SDKのsignIn()
関数を呼び出して認証フローをトリガーします。
// Reactの例
import { useLogto }from '@logto/react';
import { useEffect }from 'react';
import { useSearchParams }from 'react-router-dom';
const TokenLandingPage = () => {
const { signIn } = useLogto();
const [searchParams] = useSearchParams();
useEffect(() => {
// マジックリンクからトークンとメールを抽出
const oneTimeToken = searchParams.get('token');
const email = searchParams.get('email');
// 仮にこれがあなたのサインインリダイレクトURIであるとします
const redirectUri = 'https://yourapp.com/callback';
if (oneTimeToken && email) {
signIn({
redirectUri,
clearTokens: false, // オプション。以下の警告メッセージを参照してください
extraParams: {
'one_time_token': oneTimeToken,
'login_hint': email,
},
});
}
}, [searchParams, signIn]);
return <>しばらくお待ちください...</>;
};
詳細については、Logto Docs - マジックリンク(ワンタイムトークン)をご覧ください。
マジックリンクの使用事例
マジックリンクは第1要素認証を置き換えることができますが、多要素認証(MFA)を回避することはできません。
Logtoでは、ワンタイムトークンでマジックリンクを生成するとき、サインインかサインアップかを指定する必要はありません。メールの登録状況に基づいて自動的にフローを決定します:
- 未登録メール: マジックリンクをクリックすると、アカウント作成フローにリダイレクトされ、メール入力と確認をスキップします。ユーザーは、あなたのサインアップ設定に基づいてパスワードを設定し、プロファイル詳細(例:フルネーム)を追加するか、MFAを設定することになります。
- 登録済みメール: マジックリンクをクリックすると、第1ステップの検証(例:「メール+パスワード」または「メール+確認コード」)をバイパスします。ユーザーは、あなたのサインイン設定に基づいて、直接サインインされるか、MFAを完了するよう求められます。
Logtoは以下のシナリオでのマジックリンクをサポートします:
- 招待制の登録: テスト段階の内部ツールまたはAI製品用に、公開登録を無効にし、特定のユーザーをマジックリンクで招待することができます。
- 組織メンバーの招待: SaaS製品用として、マジックリンクを使用して新しいメンバーを組織に招待し、メンバーシッププロセスを容易にします。
- サインイン/サインアップ: マジックリンクを介してサインインまたはサインアップをメールで送信します。
現在サポートされていないもの:
さらにカスタマイズが必要な場合はお知らせください。
マジックリンクを用いた招待制の登録
新しい製品(例:AIツール)の内部テストや内部ツール用に、公開登録を無効にし、特定のユーザーのみがあなたのアプリにアクセスできるようにしたい場合があります。Logtoでこれを実装するには:
-
Console > Sign-in experience > Sign-in and sign-up > Advanced options に移動し、「Enable user registration」をオフにして公開登録を無効にします。
-
招待したいユーザーのメールアドレスを収集します(例:ウェブサイト経由または既存ユーザーの推薦)。
-
上記で説明した通りにマジック招待リンクを作成し送信します(一度限りのトークンをリクエストし、マジックリンクを作成し、Logto SDKを介して認証をトリガー)。
注意: 招待リンクの有効期限を設定してください。リンクを少なくとも1日有効とすることをお勧めします。 次のリクエストボディを使用して一度限りのトークンを生成します:
{ "email": "user@example.com", "expiresIn": 172800 // オプション。デフォルトは600(10分) }
-
ユーザーのメールにマジックリンクを送信します(例:
https://yourapp.com/landing-page?type=registrationInvitation&token=YHwbXSXxQfL02IoxFqr1hGvkB13uTqcd&email=user@example.com
)。メールテンプレートをカスタマイズします、例えば:ユーザーが「招待を受ける」をクリックすると、公開登録が無効化されていても自動的にサービスに登録されます。これを「ターゲットユーザー招待」と呼びます。
マジックリンクによる組織メンバーの招待
マルチテナント製品(例:SaaSアプリ、Slack、GitHub、Vercelなど)用として、組織メンバーシップを管理するためのシームレスなメンバー招待プロセスを提供します。マジックリンクを使用してメンバーの招待における高いコンバージョン率を確保します。
-
Logto Docsに従って組織の作成、組織の役割ベースのアクセス制御、組織管理を実装します:Logto Organizations。
-
プロダクトにおいて**"Invite members"**ワークフローを設定します。例:
-
このガイドに従って組織メンバーを招待します。
注意: メンバーを招待するとき、リクエストペイロードに以下を含めることを確認してください:- **
context: jitOrganizationIds
**でユーザーが参加する組織を指定します。 - 招待を受けるために十分であるよう、**
expiresIn
**時間を長めに設定します(例:2日間または1週間)。
ペイロードの例:
{ "email": "user@example.com", "expiresIn": 172800, // オプション。デフォルトは600(10分) "context": { "jitOrganizationIds": ["abcdefgh1234"] // 参加する組織を指定 } }
- **
-
ユーザーのメールに招待リンクを送信します(例:
https://yourapp.com/landing-page?type=organizationMemberInvitation&token=YHwbXSXxQfL02IoxFqr1hGvkB13uTqcd&email=user@example.com
)。メールテンプレートをカスタマイズします、例えば:ユーザーが**"招待を受ける"**をクリックすると、サインインまたはサインアップされ、自動的に組織に参加します。
アカウントの競合を処理
ユーザーが既にサインインしていて、他のマジックリンクをクリックした場合はどうなりますか?
アカウントの競合を正しく処理するには、次のことを確認してください:
-
"ログインサインインのプロンプト"に
login
を追加しない: サインインのプロンプトにlogin
を含めないようにしてください。不適切に設定されている場合、Logtoは競合のアカウント切り替えプロンプトをバイパスして、マジックリンクトークンに関連付けられたアカウントに自動的にサインインしてしまいます。 -
既存のトークンを保持する:
signIn()
関数を呼び出す際、clearTokens: false
パラメータを指定して既存のトークンをクリアするのを防ぐ。このオプションを使用する場合、手動でトークンをクリアすることをログインコールバックページで確認してください。
正しく設定された後のユーザーエクスペリエンスは次のようになります:
-
現在のアカウント用のマジックリンク: 既にサインインしており、同じアカウントに対するマジックリンクをクリックすると、Logtoはワンタイムトークンを検証し、必要であればユーザーを指定された組織にプロビジョニングします。
-
別のアカウント用のマジックリンク: サインインしており、別のアカウントに対するマジックリンクをクリックすると、Logtoはユーザーに以下の選択肢を促します:
- 新しいアカウントとして続ける: トークン検証後にLogtoは新しいアカウントに切り替えます。
- 現在のアカウントに留まる: トークンの検証をスキップし、現在のアカウントに戻ります。
無効になったマジックリンク用のエラーページを処理
無効なマジックリンクをユーザーがクリックすると、問題の明確な説明が表示されるエラーページにリダイレクトされます。考えられるエラーシナリオとそのメッセージは以下の通りです:
名前 | 説明 |
---|---|
token_not_found | 与えられたメールとトークンでアクティブなトークンが見つかりません。 |
email_mismatch | 与えられたトークンとメールが一致しません。 |
token_expired | トークンの有効期限が切れています。 |
token_consumed | トークンが消費されました。 |
token_revoked | トークンが無効化されました。 |
cannot_reactivate_token | トークンを再有効化できません。 |
各エラーページには具体的なメッセージが表示され、ユーザーが無効なマジックリンクの理由を理解し、次のステップについてガイドします。例:
結論
Logtoは、エンタープライズレベルのセキュリティを持つ柔軟なパスワードレスサインインフローをマジックリンクで提供します。これは、組織にユーザーを招待したり、アカウントを楽に作成させたり、煩わしさのない認証を提供したりするためのシンプルでありながら強力な方法です。また、Logtoはアカウントの競合や期限切れのトークンなどの難しい状況を処理するため、ユーザーは常に安全でストレスのないプロセスを享受できます。
防弾認証であなたのIAMをモダナイズする準備はできましたか?