この例では、DID Connect を使用して基本的なユーザーログインシステムを実装するためのステップバイステップガイドを提供します。目標は、ユーザーをDIDウォレットで認証し、名前やメールアドレスなどの基本プロファイル情報を取得することです。これは、このライブラリの最も一般的なユースケースの1つです。
WalletHandlersを使用してExpress.jsサーバーと統合し、ユーザーにprofileクレームを要求します。
仕組み
ログインプロセスは、標準のDID Connectワークフローに従います。
初期化
バックエンドは、アプリケーションのIDを持つ
WalletAuthenticatorと、セッションを管理するためのWalletHandlersインスタンスをセットアップします。ハンドラーのアタッチ
特定のハンドラーがExpressルート(例:
/api/did/login)にアタッチされます。このハンドラーは、要求する情報(クレーム)と、認証成功時に実行するロジック(onAuth)を定義します。ユーザーインタラクション
フロントエンドはDID ConnectボタンまたはQRコードを表示し、バックエンドとのセッションを開始します。
ウォレットの承認
ユーザーはDIDウォレットでQRコードをスキャンし、リクエスト(プロファイルの共有)を確認して承認します。
バックエンドのコールバック
サーバー上の
onAuthコールバックがトリガーされ、ユーザーのDID(userDid)とプロファイルデータを受信します。セッションの作成
アプリケーションはこの情報を使用して、ユーザーセッションを作成したり、トークンを発行したり、ユーザーのプロファイルをデータベースに保存したりできます。
実装
シンプルなログインエンドポイントの構築方法は次のとおりです。
ステップ1:AuthenticatorとHandlersの初期化
まず、アプリケーションの詳細でWalletAuthenticatorを設定し、セッション状態を管理するためにWalletHandlersを設定する必要があります。
Simple Login Setup
const express = require('express');
const { fromRandom } = require('@ocap/wallet');
const { WalletAuthenticator, WalletHandlers } = require('@arcblock/did-connect-js');
const SimpleStorage = require('@arcblock/did-connect-storage-nedb');
// 1. アプリケーション用のウォレットを作成
const wallet = fromRandom();
// 2. アプリとチェーン情報でオーセンティケーターを設定
const authenticator = new WalletAuthenticator({
wallet,
baseUrl: 'http://localhost:3000', // アプリケーションのベースURL
appInfo: {
name: 'Simple Login Example',
description: 'DID Connectログインを実演するためのシンプルな例',
icon: '/images/logo.png', // アプリのアイコンへのURL
},
chainInfo: {
host: 'https://beta.abtnetwork.io/api',
id: 'beta',
},
});
// 3. オーセンティケーターとストレージアダプターでハンドラーを初期化
const handlers = new WalletHandlers({
authenticator,
tokenStorage: new SimpleStorage({ dbPath: '/tmp/did_connect_login_example.db' }),
});
// 4. Expressアプリを作成
const app = express();
// アプリがプロキシの背後にある場合、動的なbaseUrl推論にこれが必要です
app.set('trust proxy', true);WalletAuthenticator: このオブジェクトは、アプリケーションのID(ウォレット)とメタデータ(appInfo、chainInfo)を保持し、これらはユーザーのウォレットに表示されます。WalletHandlers: このクラスはDID Connectセッションを調整します。セッション状態を永続化するためにauthenticatorとtokenStorageアダプターが必要です。did-connect-storage-nedbは、例に適したシンプルなファイルベースのストレージです。
ステップ2:ログインハンドラーをアタッチする
次に、handlers.attach()メソッドを使用してAPIエンドポイントを作成し、ログインフローのロジックを定義します。このメソッドは、/api/did/login/tokenや/api/did/login/statusなどのルートを自動的に作成します。
Attach Login Handler
handlers.attach(app, {
// DID Connectエンドポイントのベースパス
// 例:/api/did/login, /api/did/profile
action: 'login',
// ユーザーのウォレットから要求するクレームを定義
claims: {
profile: () => ({
fields: ['fullName', 'email'],
description: 'ログインするために、名前とメールアドレスを提供してください。',
}),
},
// 認証成功時に実行されるコールバック関数
onAuth: async ({ userDid, claims }) => {
// userDid: 認証されたユーザーのDID。
// claims: ユーザーによって提出されたクレームの配列。
try {
const profile = claims.find((x) => x.type === 'profile');
console.log('Login successful!', { userDid, profile });
// 実際のアプリケーションでは、通常次のことを行います:
// 1. userDidを使用してデータベース内のユーザーを検索または作成する。
// 2. プロファイル情報を保存する。
// 3. ユーザーのセッションを作成するか、JWTを発行する。
} catch (err) {
console.error('Error in onAuth callback', err);
}
},
});
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
console.log(`DID Connect login endpoint is ready at /api/did/login`);
});action: 'login': これにより、生成されるエンドポイントのベースパスが/api/did/loginに設定されます。claims.profile: このオブジェクトは、profileクレームを要求していることを指定します。fields配列は必要な特定の情報の一部をリストし、descriptionはユーザーのウォレットに表示され、なぜその情報が必要なのかを説明します。onAuth: これは最も重要な部分です。この関数は、ユーザーが正常に認証し、リクエストを承認した後にのみ実行されます。userDidとclaimsデータを受け取ります。ここでは、単に情報をログに記録するだけですが、実際のアプリケーションでは、ここでユーザーセッション管理を処理します。
このサーバーを実行した後、DID Connect UXライブラリを使用してフロントエンドを統合し、/api/did/loginエンドポイントを指してログインフローを開始できます。
次のステップ
これで基本的なログインシステムができたので、さらに高度な機能を探索できます。