User is not authenticated error when trying to update user attributes
See original GitHub issue** Which Category is your question related to? ** Cognito user authentication
** What AWS Services are you utilizing? ** Cognito
** Provide additional details e.g. code snippets ** Hi,
I’m trying to implement Amazon Cognito authentication in my Angular 6 application.
I can connect my user, but I want to give the users the ability to change their informations, so I created a new service to update user attributes. But when I launch the update method, I get a User is not authenticated error
. I’m still in the phase of learning Cognito, even though I have a much better understanding of how it works.
So here is the code to handle the login:
export class UserLoginService {
private onLoginSuccess = (callback: CognitoCallback, session: CognitoUserSession) => {
AWS.config.credentials = this.cognitoUtil.buildCognitoCreds(session.getIdToken().getJwtToken());
const idToken: any = session.getIdToken();
const mongoId = idToken.payload['custom:mongo_id'];
const mongoUser = this.mongoUserService.getUser(mongoId, true).subscribe();
// So, when CognitoIdentity authenticates a user, it doesn't actually hand us the IdentityID,
// used by many of our other handlers. This is handled by some sly underhanded calls to AWS Cognito
// API's by the SDK itself, automatically when the first AWS SDK request is made that requires our
// security credentials. The identity is then injected directly into the credentials object.
// If the first SDK call we make wants to use our IdentityID, we have a
// chicken and egg problem on our hands. We resolve this problem by 'priming' the AWS SDK by calling a
// very innocuous API call that forces this behavior.
const clientParams: any = {};
}
private onLoginError = (callback: CognitoCallback, err) => {
callback.cognitoCallback(err.message, null);
}
constructor(
public cognitoUtil: CognitoUtil,
private authActions: AuthActions,
private mongoUserService: MongoUserService,
private dialogService: DialogService) {
}
authenticate(username: string, password: string, callback: CognitoCallback) {
console.log('UserLoginService: starting the authentication');
const authenticationData = {
Username: username,
Password: password,
};
const authenticationDetails = new AuthenticationDetails(authenticationData);
const userData = {
Username: username,
Pool: this.cognitoUtil.getUserPool()
};
const cognitoUser = new CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
newPasswordRequired: (userAttributes, requiredAttributes) => callback.cognitoCallback(`User needs to set password.`, null),
onSuccess: result => this.onLoginSuccess(callback, result),
onFailure: err => this.onLoginError(callback, err),
mfaRequired: (challengeName, challengeParameters) => {
callback.handleMFAStep(challengeName, challengeParameters, (confirmationCode: string) => {
cognitoUser.sendMFACode(confirmationCode, {
onSuccess: result => this.onLoginSuccess(callback, result),
onFailure: err => this.onLoginError(callback, err)
});
});
}
});
}
}
The part of the CognitoUtil class implied in the connection:
@Injectable()
export class CognitoUtil {
public static _REGION = environment.region;
public static _IDENTITY_POOL_ID = environment.identityPoolId;
public static _USER_POOL_ID = environment.userPoolId;
public static _CLIENT_ID = environment.clientId;
public static _POOL_DATA: any = {
UserPoolId: CognitoUtil._USER_POOL_ID,
ClientId: CognitoUtil._CLIENT_ID
};
public cognitoCreds: AWS.CognitoIdentityCredentials;
getUserPool() {
if (environment.cognitoIdpEndpoint) {
CognitoUtil._POOL_DATA.endpoint = environment.cognitoIdpEndpoint;
}
return new CognitoUserPool(CognitoUtil._POOL_DATA);
}
getCurrentUser() {
return this.getUserPool().getCurrentUser();
}
getCognitoCreds() {
return this.cognitoCreds;
}
// This method takes in a raw jwtToken and uses the global AWS config options to build a
// CognitoIdentityCredentials object and store it for us. It also returns the object to the caller
// to avoid unnecessary calls to setCognitoCreds.
buildCognitoCreds(idTokenJwt: string) {
let url = 'cognito-idp.' + CognitoUtil._REGION.toLowerCase() + '.amazonaws.com/' + CognitoUtil._USER_POOL_ID;
if (environment.cognitoIdpEndpoint) {
url = environment.cognitoIdpEndpoint + '/' + CognitoUtil._USER_POOL_ID;
}
const logins: CognitoIdentity.LoginsMap = {};
logins[url] = idTokenJwt;
const params = {
IdentityPoolId: CognitoUtil._IDENTITY_POOL_ID, /* required */
Logins: logins
};
const serviceConfigs = <awsservice.ServiceConfigurationOptions>{};
if (environment.cognito_identity_endpoint) {
serviceConfigs.endpoint = environment.cognito_identity_endpoint;
}
const creds = new AWS.CognitoIdentityCredentials(params, serviceConfigs);
this.setCognitoCreds(creds);
return creds;
}
getCognitoIdentity(): string {
return this.cognitoCreds.identityId;
}
getAccessToken(callback: Callback): void {
if (callback == null) {
throw('CognitoUtil: callback in getAccessToken is null...returning');
}
if (this.getCurrentUser() != null) {
this.getCurrentUser().getSession(function (err, session) {
if (err) {
console.log('CognitoUtil: Cant set the credentials:' + err);
callback.callbackWithParam(null);
} else {
if (session.isValid()) {
callback.callbackWithParam(session.getAccessToken().getJwtToken());
}
}
});
} else {
callback.callbackWithParam(null);
}
}
}
And finally, the update attributes service that gives me the user is not authenticated error:
@Injectable()
export class UserUpdateService {
constructor(@Inject(CognitoUtil) public cognitoUtil: CognitoUtil) {}
update(userId: 'string', attributes: UpdateUser) {
const attributeList = [];
const dataPreferredUsername = {
Name: 'preferred_username',
Value: attributes.username
};
const dataEmail = {
Name: 'email',
Value: attributes.email
};
attributeList.push(new CognitoUserAttribute(dataPreferredUsername));
attributeList.push(new CognitoUserAttribute(dataEmail));
this.cognitoUtil.getCurrentUser().updateAttributes(attributeList, (err, result) => {
if (err) {
alert(err);
return;
}
console.log('call result: ' + result);
});
}
}
If I log this.cognitoUtil.getCurrentUser()
I have a user that corresponds to me, but the Session
and signinUserSession
are null.
I guess there’s an additional step I need to make, but I’m don’t know which one. Can anybody help?
Issue Analytics
- State:
- Created 5 years ago
- Comments:8 (4 by maintainers)
Top GitHub Comments
@richardzcode There is no MFA on my user, but I’ll try using Amplify instead of directly using Cognito!
Hey @jbprat one possible case is that MFA is required for your user. So until confirmed via SMS or TOTP the user is not really authenticated.
Actually with AWS Amplify you don’t need to interact with Cognito directly.
Auth
module of Amplify makes all these very easy.Once
signIn
happened you may check console logged ‘user’ object see if there is auser.challengeName
property to make sure