ユーザーアカウントのリンク:サーバー側実装

Auth0は、様々なIDプロバイダーのユーザーアカウントのリンクをサポートします。サーバー側コードを使用して、通常のWebアプリケーションのアカウントをリンクし、続行する前にユーザーに許可を求めることができます。コードは、ユーザーを認証し、メールアドレスを使用してユーザーを検索・特定します。その後、アプリケーションは、ターゲットアカウントの資格情報で認証することで、アカウントをリンクすることをユーザーに促し、アカウントとリンクします。

このサンプルアプリケーションの全ソースは GitHubでご覧いただけます。

  1. ユーザーをアプリケーションにログインさせる。

    ユーザーは ユニバーサルログインを使用して、アプリケーションに対して認証を受けます。詳細については、Auth0 Management APIオーディエンスのトークンを要求する(オーディエンス=https://{yourDomain}/api/v2/)、Regular Web App Quickstart(通常のWebアプリクイックスタート)をお読みください。

  2. 同じメールアドレスを持つユーザーを検索する。

    同じ検証済みメール持っているユーザーのユーザープロファイルおよびリストを取得できます。

    router.get("/", async (req, res) => {
      const { sub, email_verified } = req.openid.user;
      //fetch user profile containing the user_metadata and app_metadata properties
      try {
        let getUsersWithSameVerifiedEmail = [];
        const getUserProfile = auth0Client.getUser(sub);
        if (email_verified)
          // account linking is only offered verified email
          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);
      }
    });

    Was this helpful?

    /
    同じ検証済みメール持っているユーザーレコードの全リストを取得するには、アプリケーションは、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}`,
      });
    }

    Was this helpful?

    /

  3. アカウントのリンクをユーザーに促す。

    1. Auth0が、一致するメールアドレスを持つ1件以上のレコードを返すと、ユーザーには、アカウントのリンクを促す以下のメッセージと共に、リストが表示されます。

    2. ユーザーがアカウントをリンクしたい場合は、アカウントの隣にある[Link(リンク)]をクリックします。

      Example application with server-side account linking page

  4. ユーザーが[Link(リンク)]をクリックすると、アプリケーションは、ターゲットアカウントで認証を受けることをユーザーに求め、その後アカウントのリンクを実行します。

    以下のコードスニペットは、メタデータの検証およびマージの方法を示しています。
    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();
    }
    }

    Was this helpful?

    /

  5. アプリケーションは、update:usersスコープを持つManagement APIアクセストークンを使用してAuth0 Management APIのLink a User Accountエンドポイントを呼び出します。

メタデータマージの例

以下の例は、Node.js Auth0 SDK for API V2を使用して、セカンダリアカウントの user_metadataおよびapp_metadataをプライマリアカウントにマージする方法を明確に示しています。

/*
 * Recursively merges user_metadata and app_metadata from secondary into primary user.
 * Data of primary user takes preponderance.
 * Array fields are joined.
 */
async function mergeMetadata(primaryUserId, secondaryUserId) {
  // load both users with metedata.
  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,
  });
}

Was this helpful?

/

もっと詳しく