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

66 lines
2.6 KiB
JavaScript
Raw Normal View History

2026-05-26 06:05:33 +00:00
// Journey: (login →) refresh → me → logout
//
// Endpoints exercised:
// POST /api/v1/auth/login (tried; gracefully skipped if ZITADEL v2
// doesn't support password grant)
// POST /api/v1/auth/token/refresh (always exercised, using register tokens)
// GET /api/v1/members/me (always)
// POST /api/v1/auth/logout (always)
//
// Why the conditional login? Modern ZITADEL v2 disables OAuth resource-owner
// password grant by default ({"error":"unsupported_grant_type"}), so the
// gateway's /auth/login → zitadel.VerifyPassword pipeline returns
// 502 + 28802000 in the default k6 environment. We probe login once; if it
// 5xx's we fall back to the registration tokens so the rest of the journey
// (refresh, me, logout) still gets coverage.
import { get, post, safeJson, checkEnvelope } from '../lib/http.js';
import { registerAndConfirm, refreshToken, logout } from '../lib/auth.js';
import { cfg } from '../lib/config.js';
export const options = {
vus: 1,
iterations: 1,
thresholds: { checks: ['rate==1.0'] },
};
export default function () {
const { identity, tokens: initial } = registerAndConfirm();
// Probe login. If the env can't do password-grant, fall back to the
// tokens we already have from registerAndConfirm.
let tokens = initial;
const loginRes = post('/api/v1/auth/login', {
tenant_slug: cfg.tenantSlug,
email: identity.email,
password: identity.password,
});
if (loginRes.status === 200) {
const body = checkEnvelope(loginRes, 'POST /auth/login (happy)');
tokens = body.data;
if (tokens.uid !== initial.uid) throw new Error('login returned different uid');
} else {
const body = safeJson(loginRes) || {};
// Only the documented zitadel third-party failure is acceptable here.
if (loginRes.status !== 502 || body.code !== 28802000) {
throw new Error(
`login: unexpected failure status=${loginRes.status} body=${loginRes.body}`,
);
}
// proceed with register tokens; covered by /token/refresh below.
}
// refresh access token (works regardless of which token path we took)
const refreshed = refreshToken({ refreshToken: tokens.refresh_token });
if (!refreshed.access_token) throw new Error('refresh: missing access_token');
// GET /me with the refreshed access token
const me = checkEnvelope(
get('/api/v1/members/me', { Authorization: `Bearer ${refreshed.access_token}` }),
'GET /members/me (after refresh)',
).data;
if (me.uid !== tokens.uid) throw new Error('me.uid mismatch');
// logout
logout({ accessToken: refreshed.access_token });
}