Instead of having to do a full scan of your Cognito user pool every time, I'd use the ability of Cognito to trigger an event. For your use case Cognito can run a Lambda. You're interested in the Migrate User trigger. Basically what happens is that when the user tries to log into your system through Cognito and the user doesn't exist in the pool, a trigger is fired to let you log the user in and migrate them to Cognito.
The data coming in looks like:
{
"version": "1",
"triggerSource": "UserMigration_Authentication",
"region": "us-west-2",
"userPoolId": "us-west-2_abcdef",
"userName": "theusername@example.com",
"callerContext": {
"awsSdkVersion": "aws-sdk-unknown-unknown",
"clientId": "yourclientid"
},
"request": {
"password": "theuserpassword",
"validationData": null,
"userAttributes": null
},
"response": {
"userAttributes": null,
"forceAliasCreation": null,
"finalUserStatus": null,
"messageAction": null,
"desiredDeliveryMediums": null
}
}
Your Lambda will consume this and ultimately take the username and password and determine if it is valid. If it is, you will pass back information in the response.userAttributes
field along with things like if you want to send a Cognito welcome email (messageAction
) and some other values. For example, you may send back:
{
"version": "1",
"triggerSource": "UserMigration_Authentication",
"region": "us-west-2",
"userPoolId": "us-west-2_abcdef",
"userName": "theusername@example.com",
"callerContext": {
"awsSdkVersion": "aws-sdk-unknown-unknown",
"clientId": "yourclientid"
},
"request": {
"password": "theuserpassword",
"validationData": null,
"userAttributes": null
},
"response": {
"userAttributes": { "email":"theusername@example.com",
"email_verified": "true" }
"forceAliasCreation": null,
"finalUserStatus": "CONFIRMED",
"messageAction": "SUPPRESS",
"desiredDeliveryMediums": null
}
}
Your Lambda will look something like this in Java:
public class MigrateUserLambda implements RequestStreamHandler {
public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
LambdaLogger logger = context.getLogger();
ObjectMapper objectMapper = new ObjectMapper();
JsonNode rootNode = objectMapper.readTree(inputStream);
logger.log("input is " + objectMapper.writeValueAsString(rootNode));
String email = rootNode.path("email").asText();
String password = rootNode.path("request").path("password").asText();
// verify user name and password in MySQL. If ok...
String triggerSource = rootNode.path("triggerSource").asText();
if( triggerSource.equals("UserMigration_Authentication")) {
JsonNode responseNode = rootNode.path("response");
if (responseNode != null) {
((ObjectNode) responseNode).with("userAttributes").put("username", "theusername@example.com" );
((ObjectNode) responseNode).with("userAttributes").put("email_verified", "true" );
((ObjectNode) responseNode).put("messageAction", "SUPPRESS");
((ObjectNode) responseNode).put("finalUserStatus", "CONFIRMED");
}
}
String output = objectMapper.writeValueAsString(rootNode);
OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
writer.write(output);
logger.log("sending back " + output);
writer.close();
}
}