gpt4 book ai didi

amazon-web-services - 阻止用户自行注册联合身份提供商 (FIP),但允许在管理员添加的情况下使用 FIP 登录

转载 作者:行者123 更新时间:2023-12-04 02:27:35 29 4
gpt4 key购买 nike

我已经在 Amazon Cognito 中为我的 Web 应用程序设置了一个用户池。该应用程序不是公开的,只允许特定用户登录。亚马逊控制台中该用户池的策略只允许管理员创建新用户。
我已经通过 Facebook 和 Google 实现了登录。 Cognito 确实允许用户使用这些联合身份提供者登录应用程序,这很棒。但是,似乎任何拥有 Facebook 或 Google 帐户的人现在都可以注册。
因此,一方面,人们无法使用常规 Cognito 凭据创建自己的用户,但另一方面,如果他们使用联合身份提供者,则可以在 Cognito 中创建新用户。
有没有办法限制使用 Facebook 或 Google 登录我的应用程序,仅限用户池中已存在的用户? 这样,管理员仍然可以控制谁可以访问应用程序。我想使用联合身份提供商共享的电子邮件来检查他们是否被允许登录。
该应用程序是使用 CloudFront 设置的。我编写了一个 Lambda,它拦截源请求以检查 cookie 中的 token 并根据访问 token 的有效性授权访问。
我想避免编写额外的代码来阻止用户注册 Facebook 或 Google,但如果没有其他方法,我将更新 Lambda。

最佳答案

所以,这是我最终编写的预注册 Lambda 触发器。我花时间使用 async/await 而不是 Promises。它工作得很好,除了有一个记录在案的错误,即 Cognito 强制第一次使用外部身份提供者的用户注册,然后再次登录(因此他们会看到两次身份验证页面),然后才能访问应用程序。我有一个关于如何解决这个问题的想法,但与此同时,下面的 Lambda 做了我想要的。此外,事实证明来自 Login With Amazon 的 ID 没有使用正确的大小写,所以我不得不手动重新格式化该 ID,这很不幸。让我觉得 Cognito 触发器的实现有点问题。

const PROVIDER_MAP = new Map([
['facebook', 'Facebook'],
['google', 'Google'],
['loginwithamazon', 'LoginWithAmazon'],
['signinwithapple', 'SignInWithApple']
]);

async function getFirstCognitoUserWithSameEmail(event) {
const { region, userPoolId, request } = event;

const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider({
region
});

const parameters = {
UserPoolId: userPoolId,
AttributesToGet: ['sub', 'email'], // We don't really need these attributes
Filter: `email = "${request.userAttributes.email}"` // Unfortunately, only one filter can be applied at once
};

const listUserQuery = await cognito.listUsers(parameters).promise();

if (!listUserQuery || !listUserQuery.Users) {
return { error: 'Could not get list of users.' };
}

const { Users: users } = listUserQuery;

const cognitoUsers = users.filter(
user => user.UserStatus !== 'EXTERNAL_PROVIDER' && user.Enabled
);

if (cognitoUsers.length === 0) {
console.log('No existing enabled Cognito user with same email address found.');
return {
error: 'User is not allowed to sign up.'
};
}

if (cognitoUsers.length > 1) {
cognitoUsers.sort((a, b) =>
a.UserCreateDate > b.UserCreateDate ? 1 : -1
);
}

console.log(
`Found ${cognitoUsers.length} enabled Cognito user(s) with same email address.`
);

return { user: cognitoUsers[0], error: null };
}

// Only external users get linked with Cognito users by design
async function linkExternalUserToCognitoUser(event, existingUsername) {
const { userName, region, userPoolId } = event;

const [
externalIdentityProviderName,
externalIdentityUserId
] = userName.split('_');

if (!externalIdentityProviderName || !externalIdentityUserId) {
console.error(
'Invalid identity provider name or external user ID. Should look like facebook_123456789.'
);
return { error: 'Invalid external user data.' };
}

const providerName = PROVIDER_MAP.get(externalIdentityProviderName);

let userId = externalIdentityUserId;
if (providerName === PROVIDER_MAP.get('loginwithamazon')) {
// Amazon IDs look like amzn1.account.ABC123DEF456
const [part1, part2, amazonId] = userId.split('.');
const upperCaseAmazonId = amazonId.toUpperCase();
userId = `${part1}.${part2}.${upperCaseAmazonId}`;
}

const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider({
region
});

console.log(`Linking ${userName} (ID: ${userId}).`);

const parameters = {
// Existing user in the user pool to be linked to the external identity provider user account.
DestinationUser: {
ProviderAttributeValue: existingUsername,
ProviderName: 'Cognito'
},
// An external identity provider account for a user who does not currently exist yet in the user pool.
SourceUser: {
ProviderAttributeName: 'Cognito_Subject',
ProviderAttributeValue: userId,
ProviderName: providerName // Facebook, Google, Login with Amazon, Sign in with Apple
},
UserPoolId: userPoolId
};

// See https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_AdminLinkProviderForUser.html
await cognito.adminLinkProviderForUser(parameters).promise();

console.log('Successfully linked external identity to user.');

// TODO: Update the user created for the external identity and update the "email verified" flag to true. This should take care of the bug where users have to sign in twice when they sign up with an identity provider for the first time to access the website.
// Bug is documented here: https://forums.aws.amazon.com/thread.jspa?threadID=267154&start=25&tstart=0

return { error: null };
}

module.exports = async (event, context, callback) => {
// See event structure at https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools-working-with-aws-lambda-triggers.html
const { triggerSource } = event;

switch (triggerSource) {
default: {
return callback(null, event);
}
case 'PreSignUp_ExternalProvider': {
try {
const {
user,
error: getUserError
} = await getFirstCognitoUserWithSameEmail(event);

if (getUserError) {
console.error(getUserError);
return callback(getUserError, null);
}

const {
error: linkUserError
} = await linkExternalUserToCognitoUser(event, user.Username);

if (linkUserError) {
console.error(linkUserError);
return callback(linkUserError, null);
}

return callback(null, event);
} catch (error) {
const errorMessage =
'An error occurred while signing up user from an external identity provider.';
console.error(errorMessage, error);

return callback(errorMessage, null);
}
}
}
};

关于amazon-web-services - 阻止用户自行注册联合身份提供商 (FIP),但允许在管理员添加的情况下使用 FIP 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66447439/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com