template-monorepo/test/k6/journeys/login_mfa_full.js

46 lines
1.4 KiB
JavaScript

// Journey: login with TOTP MFA — enroll → login (mfa_required) → login/mfa → /me
//
// Endpoints:
// POST /api/v1/auth/register/confirm path (via registerAndConfirm)
// POST /api/v1/members/me/totp/enroll-start + enroll-confirm
// POST /api/v1/auth/login
// POST /api/v1/auth/login/mfa
// GET /api/v1/members/me
import { get, checkEnvelope } from '../lib/http.js';
import { registerAndConfirm, loginExpectMFA, loginMfaConfirm } from '../lib/auth.js';
import { enrollTOTP } from '../lib/member.js';
import { generateTOTP } from '../lib/totp.js';
export const options = {
vus: 1,
iterations: 1,
thresholds: { checks: ['rate==1.0'] },
};
export default function () {
const { identity, tokens } = registerAndConfirm();
const bearer = { Authorization: `Bearer ${tokens.access_token}` };
const { otpauthUrl } = enrollTOTP(bearer);
const mfa = loginExpectMFA({
email: identity.email,
password: identity.password,
});
const totpCode = generateTOTP(otpauthUrl);
const session = loginMfaConfirm({
challengeId: mfa.mfa_challenge_id,
code: totpCode,
});
if (!session.access_token) {
throw new Error('login/mfa journey: missing access_token');
}
const me = checkEnvelope(
get('/api/v1/members/me', { Authorization: `Bearer ${session.access_token}` }),
'GET /members/me (after login/mfa)',
).data;
if (me.uid !== session.uid) {
throw new Error('login/mfa journey: uid mismatch');
}
}