如何使用 OIDC 协议向 AWS Cognito 用户池中的现有用户添加身份提供商?

问题描述 投票:0回答:1

问题描述: 我在尝试使用 OIDC (OpenID Connect) 协议向 AWS Cognito 用户池中的现有用户添加身份提供商 (IdP) 时遇到了挑战。

症状: 难以确定将 OIDC 提供商链接到现有用户的适当方法。 不确定使用哪些 API 操作和参数来链接提供者。

这是我在 Node-js 中预注册 lambda 函数的代码。

const {
  CognitoIdentityProviderClient,
  ListUsersCommand,
  AdminLinkProviderForUserCommand,
} = require("@aws-sdk/client-cognito-identity-provider");

const cognitoClient = new CognitoIdentityProviderClient({});

exports.handler = async (event) => {
  if (event.triggerSource === "PreSignUp_ExternalProvider") {
    const {
      userPoolId,
      request: { userAttributes },
    } = event;
    const email = userAttributes["email"];

    // Check if the email already exists
    const userList = await cognitoClient.send(
      new ListUsersCommand({
        UserPoolId: userPoolId,
        Filter: `email = "${email}"`,
      })
    );

    if (userList.Users && userList.Users.length > 0) {
      const [providerName, providerUserId] = event.userName.split("_");

      let sourceProviderName;
      let providerAttributeName;

      switch (providerName) {
        case "google":
          sourceProviderName = "Google";
          providerAttributeName = "Cognito_Subject";
          break;
        case "azureadidp":
          sourceProviderName = "azureadidp";
          providerAttributeName = "sub";
          break;
        default:
          return event;
      }

      // Link the provider to the existing user
      await cognitoClient.send(
        new AdminLinkProviderForUserCommand({
          DestinationUser: {
            ProviderAttributeValue: userList.Users[0].Username,
            ProviderName: "Cognito",
          },
          SourceUser: {
            ProviderAttributeName: providerAttributeName,
            ProviderAttributeValue: providerUserId,
            ProviderName: sourceProviderName,
          },
          UserPoolId: userPoolId,
        })
      );
    } else {
      console.log("User not found, skipping link.");
    }
  }
  return event;
};

尝试解决: 最初尝试使用 AdminLinkProviderForUserCommand 操作,但在识别正确参数时遇到问题。 研究了 AWS 文档和在线资源,但很难找到有关 OIDC 特定实施细节的明确指导。 请求协助: 我正在寻求有关将 OIDC 提供商(例如 Google 或 AzureAD)链接到 AWS Cognito 用户池中的现有用户的正确方法和具体步骤的指导。此外,我需要帮助来确定必要的 API 操作、参数以及成功实施所需的任何其他配置步骤。

amazon-web-services aws-lambda azure-active-directory amazon-cognito openid-connect
1个回答
0
投票

据我观察,代码中的 providerUserIdOIDC 的情况下给出了不正确的大小写,因此通过创建自定义属性并将其从 OIDC 映射到 sub 并在应用程序集成部分中为自定义属性授予读取权限UserPool 然后从 event.request.userAttributes["custom:userid"] 在 lambda 函数中获取 providerUserId 它将正常工作。

这是我的 lambda 函数代码。

const {
  CognitoIdentityProviderClient,
  ListUsersCommand,
  AdminLinkProviderForUserCommand,
} = require("@aws-sdk/client-cognito-identity-provider");

const cognitoClient = new CognitoIdentityProviderClient({});

const getProviderAttributeValueSource = (
  providerName,
  providerUserId,
  event
) => {
  switch (providerName) {
    case "google":
      return providerUserId;
    case "microsoft":
      return event.request.userAttributes["custom:userid"];
    default:
      return "";
  }
};

const getProviderNameSource = (providerName) => {
  switch (providerName) {
    case "google":
      return "Google";
    case "microsoft":
      return "Microsoft";
    default:
      return "";
  }
};

exports.handler = async (event) => {
  if (event.triggerSource === "PreSignUp_ExternalProvider") {
    const {
      userPoolId,
      request: { userAttributes },
    } = event;
    const email = userAttributes["email"];

    // Check if the email already exists
    const userList = await cognitoClient.send(
      new ListUsersCommand({
        UserPoolId: userPoolId,
        Filter: `email = "${email}"`,
      })
    );

    if (userList.Users && userList.Users.length > 0) {
      const providerName = event.userName.substr(
        0,
        event.userName.indexOf("_")
      );
      const providerUserId = event.userName.substr(
        event.userName.indexOf("_") + 1
      );

      const jsonToAddProvider = {
        DestinationUser: {
          ProviderAttributeValue: userList.Users[0].Username,
          ProviderName: "Cognito",
        },
        SourceUser: {
          ProviderAttributeName: "Cognito_Subject",
          ProviderAttributeValue: getProviderAttributeValueSource(
            providerName,
            providerUserId,
            event
          ),
          ProviderName: getProviderNameSource(providerName),
        },
        UserPoolId: userPoolId,
      };

      console.log("jsonToAddProvider : ", jsonToAddProvider);

      // Link the provider to the existing user
      const response = await cognitoClient.send(
        new AdminLinkProviderForUserCommand(jsonToAddProvider)
      );
      console.log("response : ", response);
    } else {
      console.log("User not found, skipping link.");
    }
  }
  return event;
};

© www.soinside.com 2019 - 2024. All rights reserved.