Normally, you get single-use TOTP token, and need to wait for 30s for next one. This in not acceptable for tests, tho. Is there any way of skipping TOTP validation during testing or maybe guys you know some solution?
I am using cypress software.
Normally, you get single-use TOTP token, and need to wait for 30s for next one. This in not acceptable for tests, tho. Is there any way of skipping TOTP validation during testing or maybe guys you know some solution?
I am using cypress software.
I'm myself looking for a solid solution, but here's what I'm doing atm.
e2e@mydomain.com
user and logged the TOTP secret so I could use it in tests.Auth.setupTOTP(user).then(secret => {console.log(secret)})
import { authenticator } from 'otplib';
import { Amplify, Auth } from 'aws-amplify';
Amplify.configure(Cypress.env('amplifyConfig'));
export function generateOTP(secret: string, offset = 0) {
if (offset === 0) {
return authenticator.generate(secret);
}
const allOptions = authenticator.allOptions();
const delta = allOptions.step * 1000;
authenticator.options = { epoch: Date.now() + offset * delta };
const offsetToken = authenticator.generate(secret);
authenticator.resetOptions();
return offsetToken;
}
Cypress.Commands.add('loginByCognitoApi', (email: string, password: string) => {
const log = Cypress.log({
displayName: 'COGNITO LOGIN',
message: [` Authenticating | ${email} `],
autoEnd: false,
});
log.snapshot('before');
const signIn = Auth.signIn({ username: email, password });
cy.wrap(signIn, { log: false } )
.then(async user => {
// This retry logic seems to be kind of flaky
let offset = 0;
while (offset < 10) {
try {
const challengeSecret = 'OKBS5BUYW2FD32JASDQWLIVC5TNW7V3UZQZTG5OFVSFALQMK4LA';
const code = generateOTP(challengeSecret, offset++);
const result = await Auth.confirmSignIn(user, code, 'SOFTWARE_TOKEN_MFA');
return result;
} catch {}
}
})
.then((cognitoResponse: any) => {
const prefix = `${cognitoResponse.keyPrefix}.${cognitoResponse.username}`;
const { idToken, accessToken, refreshToken, clockDrift } = cognitoResponse.signInUserSession;
localStorage.setItem(`${prefix}.idToken`, idToken.jwtToken);
localStorage.setItem(`${prefix}.accessToken`, accessToken.jwtToken);
localStorage.setItem(`${prefix}.refreshToken`, refreshToken.token);
localStorage.setItem(`${prefix}.clockDrift`, clockDrift);
localStorage.setItem(`${cognitoResponse.keyPrefix}.LastAuthUser`, cognitoResponse.username);
localStorage.setItem('amplify-signin-with-hostedUI', 'false');
log.snapshot('after');
log.end();
});
});
before(() => {
cy.loginByCognitoApi(E2E_USER.email, E2E_USER.password);
cy.visit('/');
});
If anyone has a less flaky solution for signing in with amplify using TOTP in Cypress I'd like to see it also.