66 lines
2.6 KiB
JavaScript
66 lines
2.6 KiB
JavaScript
// 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 });
|
|
}
|