4

I am trying to figure out how to sign in a User with AWS Cognito. The tutorials all seem to deal with Users from a standpoint of signing up Users, not signing them in. I do not want the users to go through a sign-up process; that will be done elsewhere, by our office users. I just want to have, in this app, a flow that has them enter their existing username and password and sign in.

My current understanding of things is that Cognito User Pools only supports either sign-in using an authentication provider like Facebook or Google, or non-authenticated sign-in, which I am having trouble determining if this uses a username and password or not (I couldn't find anywhere in that flow to supply a username and password, in any case). There is also Cognito Federated Identities, which also seems to be called Cognito User Pools half the time, which has the aforementioned signup tutorials, but nothing about just signing in an existing User.

Do I have to use the Federated Identities version of User Pools in order to be able to sign in with a username and password? If not, how do I do that with non-Federated User Pools? If so, how do I make a flow just for signing in, not signing up? I am trying to grab just the pieces that look relevant from the aforementioned tutorial, but I am getting frustrated as I have been chasing my tail on this for weeks now, with only more layers of stuff that relies on other stuff that relies on other stuff in sight.

Trevortni
  • 688
  • 8
  • 23

3 Answers3

6

It's a bit confusing how the flow works. As @Ionut Trestian explains we need to create what seems to be a blank user from the pool and then authenticate that user. APIs have changed a bit, this are the updated methods.

   CognitoUserPool userPool = new CognitoUserPool(context, userPoolId, clientId, clientSecret, region;
//OR if using awsconfiguration.json
//    CognitoUserPool userPool = new CognitoUserPool(context, AWSMobileClient.getInstance().getConfiguration());

AuthenticationDetails authDetails = new AuthenticationDetails(username, password, null);

CognitoUser user = userPool.getUser();

//You might want do to the following bit inside a thread as it should be done in background
user.initiateUserAuthentication(authDetails, authHandler, true).run();
AntPachon
  • 1,152
  • 12
  • 14
  • I'm back on this project after being redirected to a different project for a while, and I've got a concern: the InitiateUserAuthentication requires both authDetails and authHandler; but the authHandler interface already requires a getAuthenticationDetails method. Will this method use the supplied authDetials instead of the one returned from the authHandler? Also, Is there an authHandler that I don't have to implement myself? I only see an empty interface. My original tutorial says to run user.getSessionInBackground instead; is there a reason to use initiateUserAuthentication instead? – Trevortni May 09 '18 at 23:22
  • Can you please explain when i log in via social what can i put in username and password. – Jay Nirmal Sep 17 '19 at 10:45
2

If the registration is done by the office and user get their username and password, so it seems you need to get the users from Cognito User Pool. For authenticating the user in Android App, first, you will need the following configuration from Cognito User Pool:

  • Pool Id
  • App client id
  • App client secret
  • AWS Region

Then you should create an instance of the user pool in your app by using CognitoUserPool, like follow:

userPool = new CognitoUserPool(context, this.poolID, this.clientID, this.clientSecret, this.awsRegion);

For allowing the user to sign-in, do the following:

public void getUser(){
    CognitoUser cognitoUser =  userPool.getUser(userId);
    cognitoUser.getSessionInBackground(authenticationHandler);
}
AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
    @Override
    public void authenticationChallenge(ChallengeContinuation continuation) {
      // Do Something
    }
    @Override
    public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
        Toast.makeText(appContext,"Sign in success", Toast.LENGTH_LONG).show();
        // Do Something
    }
    @Override
    public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
        // The API needs user sign-in credentials to continue
        AuthenticationDetails authenticationDetails = new AuthenticationDetails(userId, userPassword, null);
        // Pass the user sign-in credentials to the continuation
        authenticationContinuation.setAuthenticationDetails(authenticationDetails);
        // Allow the sign-in to continue
        authenticationContinuation.continueTask();
    }
    @Override
    public void getMFACode(MultiFactorAuthenticationContinuation multiFactorAuthenticationContinuation) {
      // Do Something
    }
    @Override
    public void onFailure(Exception exception) {
      // Do Something
    }
};

You can find more information about integrating user sign-in and sign-up here and here.

Keivan
  • 1,300
  • 1
  • 16
  • 29
  • How did you get the userId at the first place? – Debanjan Nov 06 '19 at 10:17
  • Whenever you create a user it will return userId, check the complete example [here](https://cryptiot.de/programming/adding-aws-cognito-sign-in-and-sign-up-to-android-app/) and [here](https://github.com/keivanK1/Cognito-Android-Studio). – Keivan Nov 06 '19 at 12:10
1

Cognito User Pools seem to be what you want in your app. What Cognito User Pools does is it gives you a user directory that stores user attribute data and can be used to authenticate against with username and password by your mobile app/website.

Cognito Federated Identities lets you federate users from Facebook, Google, even Cognito User Pools above for the purpose of obtaining AWS credentials to access AWS resources.

From your use case, it seems that you want to create and confirm the users from the admin side, a functionality that Cognito provides by using the adminCreateUser API. After that, the users can sign in by using username and password by using the example 6 in the tutorial you linked.

You can create an empty CognitoUser by calling getUser() on an initialized UserPool.

Code:

    user = userPool.getUser();
    AuthenticationDetails authenticationDetails = new AuthenticationDetails(email, password, null);
    user.authenticateUserInBackground(authenticationDetails, authenticationHandler);
Ionut Trestian
  • 5,473
  • 2
  • 20
  • 29
  • I'm sorry, I should have specified that step 6 there appears to require a CognitoUser to have been created from one of the previous steps. Poking around in the code, it looks like I can just use CognitoUserPool.GetUser to make a blank user; I hope that doesn't have any gotchas in it. – Trevortni Jan 04 '18 at 20:34
  • You can create an empty CognitoUser by calling getUser() on an initialized UserPool The code: user = userPool.getUser(); AuthenticationDetails authenticationDetails = new AuthenticationDetails(email, password, null); user.authenticateUserInBackground(authenticationDetails, authenticationHandler); – Ionut Trestian Jan 05 '18 at 03:26
  • I don't remember seeing an AuthenticationDetails that didn't need member functions implemented. I'll have to take another look when I get a chance. – Trevortni Jan 05 '18 at 03:56
  • AuthenticationDetails should be just a POJO that contains stuff such as user ID and password. – Ionut Trestian Jan 05 '18 at 04:39
  • authenticateUserInBackground appear to doesn't exist anymore. What about now? – Ráfagan Apr 12 '18 at 04:09
  • user.initiateUserAuthentication(.....).run() (remember to call run as the method initiateUserAuthentication returns a runnable) – AntPachon Apr 12 '18 at 11:04
  • Looks like I said AuthenticationDetails when I meant to say AuthenticationHandler seems to be an unimplemented interface. – Trevortni May 09 '18 at 23:44