so im working with aws cognito, and im a bit confused on how to get the password?
If a user enters a password into an edit text, how do i get the password the user had entered when they signed up so i can compare the password they're logged in with to the password the registered with?
Here is the code i had to register my user:
userPool.signUpInBackground(username_ET.getText().toString(), password_ET.getText().toString(), userAttributes, null, signupCallback);
And here is the code i used to log in:
private AuthenticationHandler authenticationHandler = new AuthenticationHandler()
{
#Override
public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice)
{
Log.d(COGNITO_LOGIN,"Login success I think?!");
cognitoUser.getDetailsInBackground(getDetailsHandler);
//Here i need to compare passwords before i can move on.
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId)
{
Log.d(COGNITO_LOGIN,passwordET.getText().toString());
// The API needs user sign-in credentials to continue
AuthenticationDetails authenticationDetails = new AuthenticationDetails(userId, passwordET.getText().toString(), 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) {
// Multi-factor authentication is required; get the verification code from user
multiFactorAuthenticationContinuation.setMfaCode("verificationCode");
// Allow the sign-in process to continue
multiFactorAuthenticationContinuation.continueTask();
}
#Override
public void authenticationChallenge(ChallengeContinuation continuation) {
}
#Override
public void onFailure(Exception exception)
{
// Sign-in failed, check exception for the cause
Log.d(COGNITO_LOGIN,"Login failed!");
Log.d(COGNITO_LOGIN,exception.getMessage());
exceptionMessage(exception.getMessage());
}
};
cognitoUser.getSessionInBackground(authenticationHandler);
With the authentication handler, i only need to pass in the correct username (or userID) to make the onSuccess run. Password isnt even required. So i am confused, to where the user must enter also the correct password in order for them to log in.
You don't need to compare passwords. When you sign up, Cognito stores a salt and a verifier for the password you signed up with. Cognito doesn't store your password in the form you entered it in but only a salt and verifier. When you use the code below, Cognito uses the Secure Remote Password protocol to match the verifier stored internally. Since we use the password you provided for computations, you cannot retrieve it. Note that in the onSuccess callback you will get tokens if the call is successful as noted below.
// Callback handler for the sign-in process
AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession cognitoUserSession) {
// Sign-in was successful, cognitoUserSession will contain tokens for the user
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
// The API needs user sign-in credentials to continue
AuthenticationDetails authenticationDetails = new AuthenticationDetails(userId, password, 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) {
// Multi-factor authentication is required, get the verification code from user
multiFactorAuthenticationContinuation.setMfaCode(mfaVerificationCode);
// Allow the sign-in process to continue
multiFactorAuthenticationContinuation.continueTask();
}
#Override
public void onFailure(Exception exception) {
// Sign-in failed, check exception for the cause
}
};
// Sign-in the user
cognitoUser.getSessionInBackground(authenticationHandler);
Related
I'm getting an Unkown Error when I'm trying to signin to Cognito in AWS using android ( java ) code.
public void SignIn(String phoneNumber) {
final ClientConfiguration clientConfiguration = new ClientConfiguration();
// Create a CognitoUserPool object to refer to your user pool
CognitoUserPool userPool = new CognitoUserPool(_context, poolId, _clientId,
_clientSecret, clientConfiguration);
CognitoUser user = userPool.getUser(phoneNumber);
// Callback handler for the sign-in process
AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession cognitoUserSession) {
// Sign-in was successful, cognitoUserSession will contain tokens for the user
Token = cognitoUserSession.getAccessToken();
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
// The API needs user sign-in credentials to continue
AuthenticationDetails authenticationDetails = new AuthenticationDetails(userId, _password, 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) {
// Multi-factor authentication is required; get the verification code from user
multiFactorAuthenticationContinuation.setMfaCode("123");
// Allow the sign-in process to continue
multiFactorAuthenticationContinuation.continueTask();
}
#Override
public void onFailure(Exception exception) {
// Sign-in failed, check exception for the cause
Log.d("error:", exception.getMessage());
LoginController loginController = new LoginController(_this);
loginController.NavigateToLogin();
}
};
// Sign in the user
user.getSessionInBackground(authenticationHandler);
}
I've accepted all the default roles in IAM.
Signup and confirmation of the email works fine. it's just when I want to signin after authenticationContinuation.continueTask(); it's showing unknown error. any ideas? suggestions?
Turns out I was using a wrong poolid duh!
there is a pool id in federation pool as well and I was using that instead of the one in user pool
My Android app authenticates with Cognito in an AsyncTask and receives the JWT token as part of the CognitoUserSession. This is then set in the CognitoCachingCredentialsProvider using setLogins().
I would like to retrieve this JWT token in another AsyncTask. However getLogins() on the CognitoCachingCredentialsProvider is returning a size 0 Map.
What is the easiest way to get back the token? Should I store it in Shared Preferences again?
Get/SetLogins in the SDK just update a map inside the credentials provider, they don't save it long term. If you need to access it across threads at some arbitrary time, that would be a reasonable way to accomplish it. Otherwise, just use the exact same credentials provider and it'll be there.
CognitoCachingCredentialsProvider is actually using the shared preferences to save data, but getLogins is returning a size 0 hash.
The easy way to persist data (JWT) was the shared preferences in the AsyncTask doInBackgraound method and retrieve wherever it is required.
Could get these token(refresh token / access token / id token) from aws in login time and put in preference like following:
final AuthenticationHandler authenticationCallBackManager = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession userSession, CognitoDevice newDevice) {
/*SharedPreferenceCacheManager.writeString(
LoginActivity.this,
"ACCESS_TOKEN",
userSession.getAccessToken().getJWTToken());*/
//System.out.println(userSession.getAccessToken().getJWTToken());//<<-------access token
/*SharedPreferenceCacheManager.writeString(
LoginActivity.this,
"REFRESH_TOKEN",
userSession.getRefreshToken().getToken());*/
//System.out.println(userSession.getRefreshToken().getToken());//<<---------refresh token
SharedPreferenceCacheManager.writeString(
LoginActivity.this,
"ID_TOKEN",
userSession.getIdToken().getJWTToken());
//System.out.println(userSession.getIdToken().getJWTToken());//<<-----------id token(this id uses Authorization in aws-side)
//....
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String userId) {
AuthenticationDetails authenticationDetails = new AuthenticationDetails(
userId,
String.valueOf(editTextPassword.getText()), null);
//System.out.println(CognitoServiceConstants.AUTH_PARAM_USERNAME);
//System.out.println(CognitoServiceConstants.AUTH_PARAM_REFRESH_TOKEN);
// 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 continuation) {
//....
}
#Override
public void authenticationChallenge(ChallengeContinuation continuation) {
//....
}
#Override
public void onFailure(Exception exception) {
//....
}
};
I've set up a user pool for a mobile application. The sign up process works as expected, however, attempting to log in the user in results in the following Exception:
User login alias should not be null (Service:
AmazonCognitoIdentityProvider; Status Code: 400; Error Code:
InvalidParameterException; Request ID: xxx....)
This error is being produced during the sign in attempt, called via:
CognitoUserPool.getUser(username).getSessionInBackground(authenticationHandler);
To provide a fuller snippet of the code, when the user clicks the login button, a function containing the following code is run:
AuthenticationHandler authenticationHandler = new AuthenticationHandler() {
#Override
public void onSuccess(CognitoUserSession userSession) {
Util.showMessage(mContext, "User Successfully Signed In. Session JWT Token: " + userSession.getIdToken().getJWTToken());
btnLogin.setProgress(100);
}
#Override
public void getAuthenticationDetails(AuthenticationContinuation authenticationContinuation, String UserId) {
AuthenticationDetails authenticationDetails = new AuthenticationDetails(UserId, edtPassword.getText().toString().trim(), null);
authenticationContinuation.setAuthenticationDetails(authenticationDetails);
authenticationContinuation.continueTask();
}
#Override
public void getMFACode(MultiFactorAuthenticationContinuation continuation) {
Util.showMessage(mContext, "MFA Code is Required");
// Set Up MFA Process
}
#Override
public void onFailure(Exception exception) {
Log.d(TAG, exception.toString());
Snackbar.make(edtUsername, exception.getMessage(), Snackbar.LENGTH_LONG).show();
btnLogin.setProgress(-1);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
setUpLoginClick();
}
}, 1000);
}
};
AWS.userPool(mContext).getUser(edtUsername.getText().toString()).getSessionInBackground(authenticationHandler);
AWS.userPool(Context ctx) is a utility function that i wrote to quickly retrieve the configured UserPool object.
Can anyone shed some light on why this might be happening? I can't find discussion or documentation of this error anywhere.
How do you refresh the access token using Cognito for Android? The documentation suggest the following (https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-android-sdk.html):
// Implement authentication handler
AuthenticationHandler handler = new AuthenticationHandler {
#Override
public void onSuccess(CognitoUserSession userSession) {
// Authentication was successful, the "userSession" will have the current valid tokens
// Time to do awesome stuff
}
#Override
public void getAuthenticationDetails(final AuthenticationContinuation continuation, final String userID) {
// User authentication details, userId and password are required to continue.
// Use the "continuation" object to pass the user authentication details
// After the user authentication details are available, wrap them in an AuthenticationDetails class
// Along with userId and password, parameters for user pools for Lambda can be passed here
// The validation parameters "validationParameters" are passed in as a Map<String, String>
AuthenticationDetails authDetails = new AuthenticationDetails(userId, password, validationParameters);
// Now allow the authentication to continue
continuation.setAuthenticationDetails(authDetails);
continuation.continueTask();
}
#Override
public void getMFACode(final MultiFactorAuthenticationContinuation continuation) {
// Multi-factor authentication is required to authenticate
// A code was sent to the user, use the code to continue with the authentication
// Find where the code was sent to
String codeSentHere = continuation.getParameter()[0];
// When the verification code is available, continue to authenticate
continuation.setMfaCode(code);
continuation.continueTask();
}
#Override
public void authenticationChallenge(final ChallengeContinuation continuation) {
// A custom challenge has to be solved to authenticate
// Set the challenge responses
// Call continueTask() method to respond to the challenge and continue with authentication.
}
#Override
public void onFailure(final Exception exception) {
// Authentication failed, probe exception for the cause
}
};
user.getSession(handler);
Here is why this does not work. The user object which I am getting the Session for is no longer authenticated when the token expires. So retrieving the cached user via the below, will return null
CognitoUser user = userPool.getCurrentUser();
Because the above returns null, I try to get the user object by id
CognitoUser user = userPool.getUser(userId);
Which works perfectly, except that user is not authenticated and will fail during the following callback stage because the userID is null
#Override
public void getAuthenticationDetails(final AuthenticationContinuation continuation, final String userID)
Only when I attempt this call before the token expires does this work, and I can receive a new access token. But how to do this after the token has expired? Any help on this would be appreciated. Thanks in advance
When you call getSession(...) - to get tokens - and if the cached tokens have expired, the SDK will automatically refresh tokens (as long as the refresh token has not expired). If the refresh token too has expired, then getAuthenticationDetails(...) is invoked because now the user credentials (username, password, etc) are required to get new set of tokens. It should not matter how you get the user object, i.e. through getCurrentUser() or getUser(...) methods, as long as there are valid cached tokens or if the tokens can be refreshed, you will get valid tokens with getSession(...).
Retry with the latest SDK (ver 2.3.1).
I am developing an app in Android using firebase.I have created the login activity where i have a method that logs user in when they pass the credentials(user creation is already done).Then i will save the token recieved in onAuthenticated callback so that i can log user in automatically next time when he/she opens the app without asking to enter the credentials.
Here is the code
private void loginWithPassword(final String email, String password) {
progressDialog.show();
FirebaseConnections.getConnection().authWithPassword(email, password,
new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
// Authentication just completed successfully :)
IGStorePreference.getInstance().saveString(Constants.TOKEN, authData.getToken());
IGStorePreference.getInstance().saveString(Constants.UID, authData.getUid());
IGStorePreference.getInstance().saveString(Constants.PROVIDER, authData.getProvider());
dismissProgressDialog();
}
#Override
public void onAuthenticationError(FirebaseError error) {
// Something went wrong :(
dismissProgressDialog();
Snackbar.make(parentView, error.getMessage(), Snackbar.LENGTH_LONG).show();
}
});
}
And then i check onCreate whether we have token token to log user in
private void checkIfTokenExistAndLogin() {
if (IGStorePreference.getInstance().isPrefExists(Constants.TOKEN)) {
progressDialog.show();
String provider = IGStorePreference.getInstance().getString(Constants.PROVIDER);
String token = IGStorePreference.getInstance().getString(Constants.TOKEN);
FirebaseConnections.getConnection().authWithOAuthToken(provider, token, new Firebase.AuthResultHandler() {
#Override
public void onAuthenticated(AuthData authData) {
IGStorePreference.getInstance().saveString(Constants.TOKEN, authData.getToken());
IGStorePreference.getInstance().saveString(Constants.UID, authData.getUid());
IGStorePreference.getInstance().saveString(Constants.PROVIDER, authData.getProvider());
dismissProgressDialog();
}
#Override
public void onAuthenticationError(FirebaseError firebaseError) {
dismissProgressDialog();
Snackbar.make(parentView, firebaseError.getMessage(), Snackbar.LENGTH_LONG).show();
}
});
}
}
But the problem is that i am getting an error while login user with authWithOAuthToken.Please help what i am missing.
This is the error i recieve everytime.
FirebaseError: Invalid authentication credentials provided.
authWithOAuthToken is used to login with a social provider. For example, user signs in with Google and gets an OAuth token returned from Google. Then app sends this OAuth token to Firebase auth server via authWithOAuthToken. User can log in after server verifies the OAuth token.
In your case, user logged in with email/password. The token you received was a Firebase auth token issued by Firebase auth server not an OAuth token issued by social provider.
Please refer to the doc for details: https://firebase.google.com/support/guides/firebase-android#sign_a_user_in_with_a_social_provider_numbered