简体   繁体   中英

iOS - AWS Cognito - Check if user already exists

I want to allow a user to enter their email address/password in a field. Upon continuing, I want to run a check to see if that user already exists. 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, etc.

I cannot for the life of me find documentation on how to log a user in using AWS Cognito. I should be able to pass email/pass 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..this is my last resort.

In the current SDK, calling getUser on your AWSCognitoIdentityUserPool just constructs the in-memory user object. To make the call over the network, you need to call the getSession method on the constructed user. Here's a Swift 3 method I wrote to check whether an email is available:

/// Check whether an email address is available.
///
/// - Parameters:
///   - email: Check whether this email is available.
///   - completion: Called on completion with parameter true if email is available, and false otherwise.
func checkEmail(_ email: String, completion: @escaping (Bool) -> Void) {
        let proposedUser = CognitoIdentityUserPoolManager.shared.pool.getUser(email)
        UIApplication.shared.isNetworkActivityIndicatorVisible = true
        proposedUser.getSession(email, password: "deadbeef", validationData: nil).continueWith(executor: AWSExecutor.mainThread(), block: { (awsTask) in
            UIApplication.shared.isNetworkActivityIndicatorVisible = false
            if let error = awsTask.error as? NSError {
                // Error implies login failed. Check reason for failure
                let exceptionString = error.userInfo["__type"] as! String
                if let exception = AWSConstants.ExceptionString(rawValue: exceptionString) {
                    switch exception {
                    case .notAuthorizedException, .resourceConflictException:
                        // Account with this email does exist.
                        completion(false)
                    default:
                        // Some other exception (e.g., UserNotFoundException). Allow user to proceed.
                        completion(true)
                    }
                } else {
                    // Some error we did not recognize. Optimistically allow user to proceed.
                    completion(true)
                }
            } else {
                // No error implies login worked (edge case where proposed email
                // is linked with an account which has password 'deadbeef').
                completion(false)
            }
            return nil
        })
    }

For reference, my ExceptionString enum looks like this:

public enum ExceptionString: String {
    /// Thrown during sign-up when email is already taken.
    case aliasExistsException = "AliasExistsException"
    /// Thrown when a user is not authorized to access the requested resource.
    case notAuthorizedException = "NotAuthorizedException"
    /// Thrown when the requested resource (for example, a dataset or record) does not exist.
    case resourceNotFoundException = "ResourceNotFoundException"
    /// Thrown when a user tries to use a login which is already linked to another account.
    case resourceConflictException = "ResourceConflictException"
    /// Thrown for missing or bad input parameter(s).
    case invalidParameterException = "InvalidParameterException"
    /// Thrown during sign-up when username is taken.
    case usernameExistsException = "UsernameExistsException"
    /// Thrown when user has not confirmed his email address.
    case userNotConfirmedException = "UserNotConfirmedException"
    /// Thrown when specified user does not exist.
    case userNotFoundException = "UserNotFoundException"
}

Some clarification is in order. Cognito has several parts. The part that does "Authentication" (which is what you are talking about) is called "Cognito User Pools". Not to be confused with Cognito Federated Identity Pools.

With User Pools you can create usernames and password combinations with attributes, and these can be used to authenticate and deliver a persistent, cross device, Cognito Federated identity identityId to a user (across multiple devices).

Once logged in, the Federated Identity Pool is hooked to roles which can get your "Authorized" to use AWS services (like Dynamo DB etc).

It can be tricky to get all these parts working together and AWS has an online site called "Mobile Hub" that will build code for you and download an xcode project. This process configures the Federated Identity Pool and the User Pool correctly, and connects them all up to a set of example code.

Connecting the credentials provider to the user pool to the identity pool is a bit counterintuitive, but the AWSIdentityManager in the aws-mobilehub-helper-ios on github manages all that for you. So I would recommend starting with mobile hub on the console.

Cognito is a somewhat confusing system, here is a link to a brief powerpoint that hits the highlights of how it works (for people that can't understand the AWS docs (like me)).

With that said, "how to check if a user already exists?"

The most reasonable approach is to create the user (via signup), and get a reject if the name is in use, and suggest that your user try a different username. With respect to the email being in use, you will get that reject upon confirmation (signup sends confirmation id's by email and/or via text). This can be overridden to reclaim the email address, or you can do a test beforehand to see if the email is in use by attempting to log in and looking at the failure code.

you can fetch the user as the other answer suggests, however if you have established in user pools an alias for login (like email) you will find this problematic, because this just tells you if someone has the user name, not if someone is already using the email address, and you will get a reject later at confirmation time.

ListUsers is now a nice way to check for existing usernames.

https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.html

You can also look for existing emails, phone numbers, and other default attributes.

Here is a simple .NET example:

    Dim userRequest = New ListUsersRequest With {
            .UserPoolId = "poolId",
            .Filter = "username = bob@email.com"
        }
    Dim response = amazonCognitoIdentityProviderClient.ListUsers(userRequest)
    Debug.WriteLine(response.Users.Count)

Check user name exists by providing the userName before doing login process. If you get value for getUser method then the user exists, if you get nil or error then user doesn't exists.

    let pool = AWSCognitoIdentityUserPool(forKey: "UserPool")
    let user: AWSCognitoIdentityUser = pool.getUser("userName")

Thanks:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM