ユーザーアカウントのリンク:サーバー側実装
Auth0は、様々なIDプロバイダーのユーザーアカウントのリンクをサポートします。サーバー側コードを使用して、通常のWebアプリケーションのアカウントをリンクし、続行する前にユーザーに許可を求めることができます。コードは、ユーザーを認証し、メールアドレスを使用してユーザーを検索・特定します。その後、アプリケーションは、ターゲットアカウントの資格情報で認証することで、アカウントをリンクすることをユーザーに促し、アカウントとリンクします。
このサンプルアプリケーションの全ソースは GitHubでご覧いただけます。
ユーザーをアプリケーションにログインさせる。
ユーザーは ユニバーサルログインを使用して、アプリケーションに対して認証を受けます。詳細については、Auth0 Management APIオーディエンスのトークンを要求する(オーディエンス=
https://{yourDomain}/api/v2/
)、Regular Web App Quickstart(通常のWebアプリクイックスタート)をお読みください。同じメールアドレスを持つユーザーを検索する。
同じ検証済みメール持っているユーザーのユーザープロファイルおよびリストを取得できます。
同じ検証済みメール持っているユーザーレコードの全リストを取得するには、アプリケーションは、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?
/アカウントのリンクをユーザーに促す。
Auth0が、一致するメールアドレスを持つ1件以上のレコードを返すと、ユーザーには、アカウントのリンクを促す以下のメッセージと共に、リストが表示されます。
ユーザーがアカウントをリンクしたい場合は、アカウントの隣にある[Link(リンク)]をクリックします。
ユーザーが[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?
/アプリケーションは、
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?