In my Android app, I use AWS Cognito to allow my users to sign up and login. I configured my identity pool so it allows guest users (unauthenticated users) in my app.
So everytime my user logs in or logs out, I call the following code to get an identity ID:
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
this,
"eu-central-1:12345678-1234-5678-9012-1234567890ab",
"eu-central-1");
credentialsProvider.clearCredentials();
credentialsProvider.getIdentityId();
When my user logs in, it creates a new identity the first time, then the user gets the same identity everytime he logs in. But everytime he logs out, a new identity is created, since he's now a "guest" user.
Is that the expected behavior? And if yes, how can I remove an unused identity programmatically (for example when the user logs in, so the "guest" identity is now useless, since a new one will be created when he logs out)?
Thanks for your help.
From the docs, we have:
getIdentityId() Gets the Cognito identity id of the user. The first time when this method is called, a network request will be made to retrieve a new identity id. After that it's saved in SharedPreferences.
clearCredentials() Destroy all the saved AWS credentials but not the identity Id.
so, the behavior you described is totally normal according to the docs.
Now, let's find an approach to deal with the problem.
if you want to continue with your proposition, and delete the identity programmatically after the logout, you can use deleteUser() method from AWSJavaSDK.
However, if you want to keep the same identity for the same user after the logout, you shouldn't clear the cache, cause the won't keep the user any trace of its identity.
I hope this will help.
Related
I create a Firebase Auth user with an email and password
User logs in
User decides to add a phone number to their profile
I call verifyPhoneNumber with an intent to receive a code, call PhoneAuthProvider.getCredential(...) and link resulting AuthCredential to the email and password.
Instead, Android auto retrieves the code, user automatically sign-ins with phone number, their UID changes (it's a new user) and there's no way to link phone credentials back to the original email/password user. To perform a successful link I need to see the SMS code, which is nowhere to be found in case of successful auto sign-in.
????
NO PROFIT.
Any ideas? I tried to set the timeout to 0 for verifyPhoneNumber but auto login still works. Accepting defeat and just link EmailAndPassword credentials to phone number instead of vice versa is not an option, because it will require a massive copying of data from old user record into new, changing all references to this UID everywhere, etc.
verifyPhoneNumber resolves with a PhoneAuthCredential.
It doesn't matter whether the code is auto-retrieved or instant validation occurs. A PhoneAuthCredential is outputted on verifyPhoneNumber completion.
That credential can either be used to signInWithCredential for sign-in or to link to an existing user via linkWithCredential.
I have been reading around on different ways to refresh the cognito session after 1 hour, and I have yet to get a conclusive answer from aws team or anyone else. How do you get new tokens after the sessions have expired without re-authenticating, that is, the user has to login again (enter their password/email credentials).
There is a method refresh() in CognitoCachingCredentialsProvider class, that I believe refreshes the session. However, after that is called how do you get the new tokens (idToken/accessToken/refreshToken)? In my case the refreshToken is set to the maximum expiration time which is about 10 years.
The only way to get new tokens as I have done so far, is through user authentication when the user is logging in, where cognitoUser.getSessionInBackground(authenticationHandler) is called. This interface provides the tokens retrieved from CognitioUserSession. It seems very counterproductive for my application in particular to prompt the user to login, using their password each time after 1 hour.
I would like to add one more thing, is it even possible to get new tokens after the idToken and accessToken have expired? Looking at the aws cognito raw code, I have not seen an interface that provides that outside of login in the user despite what the documentation says.
I have problem with keeping user logged in to AWS Cognito in my android app. This is the code which checks that:
CognitoUser user = AppHelper.getPool().getCurrentUser();
username = user.getUserId();
if(username != null) {
AppHelper.setUser(username);
inUsername.setText(user.getUserId());
user.getSessionInBackground(authenticationHandler);
}
The problem is that sometimes (I guess after some time) the app forgets the user and that code:
user.getUserId();
Returns null. However that is never null:
AppHelper.getPool().getCurrentUser();
My code basis on the code from the sample app so I cannot understand why it doesn't work. I though that there might be a problem with Cognito pool, so I changed in devices options to always remember user device, but the issue didn't disappear.
Hi Grzegorz Brzęczyszczykiewicz,
user.getUserId(); will always return the userid, if the referenced CognitoUser object was created with CognitoUser user = AppHelper.getPool().getCurrentUser(); after a user had previously successfully signed-in.
An explanation for the behavior you are seeing could be that the user was changed to reference a CognitoUser object which was not set to any user. This can happen when CognitoUser user = AppHelper.getPool().getCurrentUser(); is executed after clearing app data on the Android device.
Can you give provide any more details about your app, to better understand the issue? When the app executes user.getSessionInBackground(authenticationHandler);, are you able to successfully sign-in?
I have communicate with API using retrofit. When the user is log in, I save account to database and when the user go to app next time, I get data from database (so I skipped login screen). Problem is when user's token expires.
How to handle the situation?
in login fragment
PSEUDOCODE
user = ... //get user from database
if(user != null) {
startActivityAccountActivity();
}
//onButtonClick
emailLogin();
Don't go to your "logged in" activity just because you have a token saved, because as you have correctly noticed, it may be invalid. Try authenticating with the API when you get the token, and only go to the "logged in" activity if it indeed worked. Otherwise proceed as if there was no token saved (and remove the expired one from the database).
You should also note that the token may expire when the user is in the "logged in" activity. For example, the user logged in, used the app and then went to another app from the recents screen. A week later he/she returns to your app with the "logged in" activity open, but in the mean time the token has expired and nothing will work. So you should also check if the token still works there, maybe in the onStart() of the activity.
As indramurari said, you can also handle it on the backend if you control it. But keep in mind that it doesn't solve your inherent problem of handling expired tokens, a refresh token may also expire and you are back to square one. If you make refresh tokens not expire you can just make the login tokens not expire. (This paragraph would be a comment on his answer, but I don't have enough reputation.)
It depends on your back end security level. You have two options to handle this situation.
Build some mechanism on back end side so that your server will send some refresh-token along with the user's token at the time of login to Android device. Whenever user's token get expired then request from Android device to your server to obtain new user's token by sending old user's token along with refresh-token. And you can use that new user's token for future. Repeat this whenever user's token get expired.
Note - refresh-token is for validating if it is valid resource who is requesting for a user's token.
You can delete the user account from database and tell user to Re-Login.
I have been trying to solve this for a few days now but i can't figure out what the problem is.
I have a user pool and an identity pool on AWS Cognito. I have run the sample code and used it to log in and register users with Facebook and Google+ successfully. After login i am able to authenticate using the token to use SNS or the Sync services.
I have registered a user and got a token (after logging in) with Cognito Identity. However the next step is to use the token to authenticate into the identity pool. This is where i keep getting the error
I have followed the instructions from Integrating User Pools with Amazon Cognito Identity and I get a token which I then try to pass it along with the pool id to the credentials provider.
credentialsProvider.clear();
credentialsProvider.withLogins(loginMap).refresh();
My code fails on refresh(). At this point credentialsProvider is a AWSBasicCognitoIdentityProvider and refresh() fails in the super.refresh() which calls getIdentityId() in the abstract parent class AWSAbstractCognitoIdentityProvider
#Override
public String getIdentityId() {
if (identityId == null) {
GetIdRequest getIdRequest = new GetIdRequest()
.withAccountId(getAccountId())
.withIdentityPoolId(getIdentityPoolId())
.withLogins(loginsMap);
appendUserAgent(getIdRequest, getUserAgent());
GetIdResult getIdResult = cib.getId(getIdRequest);
No matter what values i put in the loginsMap, i get the error
Invalid login token. Issuer doesn't match providerName
at cid.getid(getIdRequest).
Most of the code is available to download free if you create an app in the Mobile Hub and generate the code. You can then configure authentication providers - FB, Google , etc.
What am I doing wrong ?
Thanks.
Edit : Here are examples of what i have tried
The token is always the object in the map. Below are the different keys
"cognito-identity.amazonaws.com"
the User Pool id - us-east-1_xxxxxxxxx
the User Pool ARN - cognito-idp:us-east-1:xxxxxxxxxxxx:userpool/us-east-1_xxxxxxxxx
OK i found the answer - I was putting in the wrong key value in the loginMap.
it should be
cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>
as it says in the documentation linked in the question
I don't know how I didn't see that.