メインコンテンツへスキップ
Auth0 は、さまざまな のユーザーアカウントのリンクをサポートしています。サーバーサイドコードを使用すると、通常の Web アプリケーションでアカウントをリンクできます。その際、処理を進める前にユーザーに関与してもらい、許可を得ることができます。コードではユーザーを認証し、メールアドレスを使用して該当するユーザーを検索および特定します。次に、アプリケーションは対象アカウントの認証情報で認証するようユーザーに求め、アカウントをリンクするよう促した後、アカウントをリンクします。 このサンプルアプリケーションの完全なソースは GitHub で確認できます。
  1. ユーザーをアプリケーションへログインさせます。
    ユーザーは Universal Login を使用してアプリケーションにサインインします。詳しくは、Auth0 Management API のオーディエンス (audience=https://{yourDomain}/api/v2/) に対するトークンをリクエストする 通常の Web アプリのクイックスタート を参照してください。
  2. 同じメールアドレスを持つユーザーを検索します。
    ユーザープロフィールと、同じ確認済みメールアドレスを持つユーザーの一覧を取得できます。
    router.get("/", async (req, res) => {
      const { sub, email_verified } = req.openid.user;
      //user_metadataとapp_metadataプロパティを含むユーザープロフィールを取得する
      try {
        let getUsersWithSameVerifiedEmail = [];
        const getUserProfile = auth0Client.getUser(sub);
        if (email_verified)
          // アカウントリンクはメールアドレスが確認済みの場合のみ提供される
          getUsersWithSameVerifiedEmail = auth0Client.getUsersWithSameVerifiedEmail(
            req.openid.user
          );
    
        const [user, suggestedUsers] = await Promise.all([
          getUserProfile,
          getUsersWithSameVerifiedEmail,
        ]);
    
        const flashError = clear(req);
        res.render("user", {
          user,
          suggestedUsers,
          wrongAccountError: flashError && flashError === Errors.WrongAccount,
        });
      } catch (err) {
        debug("GET /user[s] failed: %o", err);
        res.render("error", err);
      }
    });
    
    同じメールアドレスを持つすべてのユーザーレコードの一覧を取得するには、アプリケーションで read:users スコープを持つ Management API アクセストークン を使用して、Auth0 Management API の Get Users By Email エンドポイント を呼び出します。
    const request = require('request');
    class Auth0Client {
    ...
    async getUsersWithSameVerifiedEmail({ sub, email }) {
      return await this.request({
        url: `${process.env.ISSUER_BASE_URL}/api/v2/users-by-email?email=${email}`,
      });
    }
    
  3. ユーザーにアカウントのリンクを促します。
    1. Auth0 が一致するメールアドレスを持つレコードを 1 件以上返した場合、ユーザーにはその一覧と、アカウントをリンクするよう促す次のメッセージが表示されます。
    2. ユーザーが特定のアカウントをリンクする場合は、該当するアカウントの横にある Link をクリックします。
      サーバー側のアカウントリンクページを表示したアプリケーションの例
  4. ユーザーが Link をクリックすると、アプリケーションは対象のアカウントで認証するようユーザーに求め、その後アカウントリンクを実行します。
    セカンダリアカウントの user_metadata を保持してマージするには、API エンドポイントを呼び出す前に、その user_metadata を取得し、プライマリアカウントのメタデータにマージする必要があります。アカウントをリンクすると、セカンダリアカウントのメタデータは破棄されます。アカウントリンクを開始する際は、どの ID をプライマリアカウントとして使用し、どの ID をセカンダリアカウントとして使用するかを選択できます。この選択は、プライマリプロファイルに保持したい属性セットに応じて決まります。
    次のコードスニペットは、メタデータを検証してマージする方法を示しています。
    async function accountLink(req, res, next) {
    const {
      linking: { targetUserId },
    } = req.appSession;
    const { sub: authenticatedTargetUserId } = req.openidTokens.claims();
    if (authenticatedTargetUserId !== targetUserId) {
      debug(
        "Skipping account linking as the authenticated user(%s)  is different than target linking user (%s)",
        authenticatedTargetUserId,
        targetUserId
      );
      set(req, Errors.WrongAccount);
      return next();
    }
    
    debug(
      "User %s succesfully authenticated. Account linking with %s... ",
      authenticatedTargetUserId,
      targetUserId
    );
    const { id_token: targetIdToken } = req.openidTokens;
    const { sub: primaryUserId } = req.appSession.claims;
    
    try {
      await mergeMetadata(primaryUserId, authenticatedTargetUserId);
      await auth0Client.linkAccounts(primaryUserId, targetIdToken);
      debug("Accounts linked.");
    } catch (err) {
      debug("Linking failed %o", err);
    } finally {
      next();
    }
    }
    
  5. アプリケーションは、update:users スコープを持つ Management API アクセストークン を使用して、Auth0 Management API の ユーザーアカウントのリンク用エンドポイント を呼び出します。

メタデータのマージ例

次の例では、API V2 用 Node.js Auth0 SDK を使用して、セカンダリアカウントの user_metadataapp_metadata をプライマリアカウントに明示的にマージする方法を示します。
/*
 * セカンダリユーザーの user_metadata と app_metadata をプライマリユーザーに再帰的にマージします。
 * プライマリユーザーのデータが優先されます。
 * 配列フィールドは結合されます。
 */
async function mergeMetadata(primaryUserId, secondaryUserId) {
  // 両方のユーザーをメタデータとともに読み込みます。
  const [primaryUser, secondaryUser] = await Promise.all(
    [primaryUserId, secondaryUserId].map((uid) => auth0Client.getUser(uid))
  );

  const customizerCallback = function (objectValue, sourceValue) {
    if (_.isArray(objectValue)) {
      return sourceValue.concat(objectValue);
    }
  };
  const mergedUserMetadata = _.merge(
    {},
    secondaryUser.user_metadata,
    primaryUser.user_metadata,
    customizerCallback
  );
  const mergedAppMetadata = _.merge(
    {},
    secondaryUser.app_metadata,
    primaryUser.app_metadata,
    customizerCallback
  );
  await auth0Client.updateUser(primaryUserId, {
    user_metadata: mergedUserMetadata,
    app_metadata: mergedAppMetadata,
  });
}

関連情報