ethan123
ethan123

Reputation: 1084

CognitoCachingCredentialsProvider getCachedIdentityId is null after app close and re-open

I might be misunderstanding the intended behavior of this method, but this is what I am trying to use it for:

-User logs in successfully -User closes app completely (closes in background as well) -User opens app again and doesn't have to log in again because CognitoCachingCredentialsProvider can check locally on the device to see she's still logged in

The way I tried to accomplish this is to check, before being prompted to log in, what getCachedIdentityId() returns. If it returns not null, then that means that she's still logged in, because there was nothing that cleared her credentials from the device. Here's what my framework looks like. I'm using developer authenticated method:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.util.Log;

import com.amazonaws.auth.AWSAbstractCognitoIdentityProvider;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.mobileconnectors.cognito.*;
import com.amazonaws.regions.Regions;

public class Util {
    private final static String TAG = "Util";

    private static final String AWS_ACCOUNT_ID = {acct id};
    private static final String COGNITO_POOL_ID = {pool id};
    private static final String COGNITO_ROLE_AUTH = {auth arn};
    private static final String COGNITO_ROLE_UNAUTH = {unauth arn}

    private static CognitoCachingCredentialsProvider sCredProvider;
    private static UserIdentityProvider sIdProvider;
    private static CognitoSyncManager sSyncManager;

    private Util() {
    }

    public static CognitoCachingCredentialsProvider getCredProvider(
            Context context) {
    if (sCredProvider == null) {
        if (sIdProvider == null) {
            CognitoCachingCredentialsProvider tmpProvider = new CognitoCachingCredentialsProvider(
                    context.getApplicationContext(), AWS_ACCOUNT_ID,
                    COGNITO_POOL_ID, COGNITO_ROLE_UNAUTH,
                    COGNITO_ROLE_AUTH, Regions.US_EAST_1);
            if (tmpProvider.getCachedIdentityId() != null) {
                sCredProvider = tmpProvider;
            } else {
                sCredProvider = null;
            }
        } else {
            sCredProvider = new CognitoCachingCredentialsProvider(
                    context.getApplicationContext(), sIdProvider,
                    COGNITO_ROLE_UNAUTH, COGNITO_ROLE_AUTH);
            Map logins = new HashMap();
            logins.put({Developer Provider Name}, sIdProvider.getToken());
            sCredProvider.setLogins(logins);
        }
    }
    return sCredProvider;
    }

    public static UserIdentityProvider getIdentityProvider(Context context,
            String email, String pwd) {
        if (sIdProvider == null) {
            sIdProvider = new UserIdentityProvider(AWS_ACCOUNT_ID,
                COGNITO_POOL_ID, context.getApplicationContext());
        }
        return sIdProvider;
    }

    public static boolean isLoggedIn(Context context) {
        if (getCredProvider(context) == null) {
            return false;
        }
        return true;
    }

    protected static class UserIdentityProvider extends
            AWSAbstractCognitoIdentityProvider {

        private Context context;
        private String email;
        private String password;

        public UserIdentityProvider(String accountId, String identityPoolId,
                Context c) {
            super(accountId, identityPoolId);
            context = c;
            email = em;
            password = pwd;
        }

        @Override
        public String refresh() {
            try {
                ServerCommunicator server = new ServerCommunicator(context);
                if (email != null && password != null) {
  //this is a server call, which makes the call GetOpenIdTokenForDeveloperIdentityRequest after I authenticate the user and send AWS my user's token
                    String response = server.initUserLoginAsyncTask()
                            .execute(email, password).get();
                    prefs.setAllUserSharedPrefs(response);
                    JSONObject responseJSON = new JSONObject(response);
                    String identityId = responseJSON.getString("id");
                    String token = responseJSON.getString("token");
                    if (token != null && identityId != null) {
                        this.setToken(token);
                        this.setIdentityId(identityId);
                        update(identityId, token);
                        return token;
                }
            }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public String getProviderName() {
            return {Developer Provider Name};
        }

    }

} 

I simply call the isLoggedIn method from this class to see if there's an IdentityId stored locally. However, this isn't working as expected. I can see from debugging that getCachedIdentityId is always null (even directly after initializing CognitoCachingCredentialsProvider and adding the token to the logins map) and I am always prompted to log in again whenever I open the app after it has been closed. When does the IdentityId actually get stored locally and is my logic correct in general?

Additional Code

import java.util.concurrent.ExecutionException;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class LoginActivity extends Activity {

private final String TAG = "LoginActivity";

private EditText etEmail, etPwd;
private Button bLogin, bGoToRegister;
private ServerCommunicator server;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Log.i(TAG, "onCreate");
    server = new ServerCommunicator(this);
    if (Util.isLoggedIn(this)) {
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        return;
    }
    this.setContentView(R.layout.activity_login);
    etEmail = (EditText) findViewById(R.id.etEmail);
    etPwd = (EditText) findViewById(R.id.etPassword);
    bLogin = (Button) findViewById(R.id.bLogin);
    bGoToRegister = (Button) findViewById(R.id.bGoToRegister);
    bLogin.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            String email = etEmail.getText().toString();
            String pwd = etPwd.getText().toString();
            Util.getIdentityProvider(v.getContext()).setEmail(email);
            Util.getIdentityProvider(v.getContext()).setPassword(pwd);
            String token = Util.getIdentityProvider(v.getContext()).refresh();
            if (token != null) { 
                Intent intent = new Intent(v.getContext(), MainActivity.class); 
                startActivity(intent);
            }  else {
                 Toast.makeText(v.getContext(), "Invalid username/password",
                 Toast.LENGTH_SHORT).show();
            }
        }
    });
}
}

The above is my LoginActivity. When the app starts the MainActivity, I have the following snippet at the beginning of my onCreate method:

if (!Util.isLoggedIn(this)) {
        Intent intent = new Intent(this, LoginActivity.class);
        startActivity(intent);
}

This call initializes the CognitoCachingCredentialsProvider. I assumed that this would be when the IdentityId gets cached, but my debugging has revealed that even directly after this block, getCachedIdentityId() still returns null. Am I way off base with how I'm trying to use this class?

Upvotes: 1

Views: 1487

Answers (1)

Jeff Bailey
Jeff Bailey

Reputation: 5775

I have one suggestion. The CognitoCachingCredentialsProvider is what saves the identityId as it's changed. It doesn't start listening, though, until it's been initialized, and the change occurs on refresh call to your identity provider.

Can you try moving the initialization of the CognitoCachingCredentialsProvider to before the refresh call (but after your identity provider initialization)?

Edit:

Update will set the identityId and token, however explicit calls made just beforehand may cause it to think no change is being made. Can you try eliminating the setter calls as well?

Upvotes: 1

Related Questions