JAVA- AWS Cognito -Check if a user exists in Cognito User pool

4.5k views Asked by At

I want to allow a user to enter their username/password in a field. Upon continuing, I want to run a check to see if that user already exists in the user pool. If they do, log them in and continue with app, if they do not, move to account creation flow where they will be instructed to add name, phone number, email etc.

I cannot find documentation on how to log a user in using AWS Cognito. I should be able to pass username/passcode in a call and get a response back that says User Exists/User does not exist or whatever! Am I missing something here?

Any help would be greatly appreciated. I've scoured the documentation...

3

There are 3 answers

2
Yuriy P On BEST ANSWER

To list users you can use AWS Java SDK:

public static void list() {
    AwsBasicCredentials awsCreds = AwsBasicCredentials.create(AWS_KEY,
            AWS_SECRET);

    CognitoIdentityProviderClient identityProviderClient =
            CognitoIdentityProviderClient.builder()
                    .credentialsProvider(StaticCredentialsProvider.create(awsCreds))
                    .region(Region.of(REGION))
                    .build();

    final ListUsersRequest listUsersRequest = ListUsersRequest.builder()
            .userPoolId(POOL_ID)
            .build();

    ListUsersResponse result = identityProviderClient.listUsers(listUsersRequest);

    System.out.println("Has users:"+result.hasUsers());
    result.users().stream().map(u->u.username()).forEach(System.out::println);
}

it requires next dependecies (please use latest versions):

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>aws-core</artifactId>
  <version>2.13.57</version>
</dependency>

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>cognitoidentityprovider</artifactId>
  <version>2.13.57</version>
</dependency>

Here is a code sample of how to login user from Java.

0
stdunbar On

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": "[email protected]",
    "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": "[email protected]",
    "callerContext": {
        "awsSdkVersion": "aws-sdk-unknown-unknown",
        "clientId": "yourclientid"
    },
    "request": {
        "password": "theuserpassword",
        "validationData": null,
        "userAttributes": null
    },
    "response": {
        "userAttributes": { "email":"[email protected]",
                            "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", "[email protected]" );
                ((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();
    }
}
0
ᴛʜᴇᴘᴀᴛᴇʟ On

To check if the user exists or not, all you need is username.

So for your scenario, trigger the myMethod() below after user enters username and password. That will

  1. Check if the username is already in user
  2. If username exists, perform sign in
  3. If username does not exists, create account

/**
* let's say you call this method when user enters username and password
* @param context context
* @param identityProvider cognito client
* @param username user entered username
* @param password user entered password
* @return
*/
private void myMethod(Context context, AWSCognitoIdentityProvider identityProvider, String username, String password) {
    
    boolean userExists = userExists(context, identityProvider, username);
    
    if(userExists) {
        // perform sign in with provided password
    } else {
        // create account
    }
}


/**
* @param context context
* @param identityProvider cognito client
* @param username user entered username
* @return true if username is already in use, false otherwise
*/
private boolean userExists(Context context, AWSCognitoIdentityProvider identityProvider, String username) {
    LambdaLogger logger = context.getLogger();

    try {
        AdminGetUserRequest getUserRequest = new AdminGetUserRequest();
        getUserRequest.setUserPoolId("cognitoPoolId");
        getUserRequest.setUsername(username);

        AdminGetUserResult getUserResult = identityProvider.adminGetUser(getUserRequest);

        return true;
    } catch (UserNotFoundException userNotFoundException) {
        logger.log("UserNotFoundException! " + userNotFoundException.toString());
        return false;
    } catch (Exception e) {
        return false;
    }
}