hcengineering/platform · error
Admins only
Error message
Admins only
What it means
withAdmin rejects with 401 'Admins only' when a token IS present but the caller is neither the system account (req.token.account !== systemAccountUuid) nor flagged as admin (req.token.extra?.admin !== 'true'). Authentication succeeded; authorization failed. This guard protects admin-only payment endpoints.
Source
Thrown at services/payment/pod-payment/src/middleware.ts:43
}
export const withToken = (req: RequestWithAuth, res: Response, next: NextFunction): void => {
const token = extractToken(req.headers)
if (token === undefined || token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
req.token = token
next()
}
export const withAdmin = (req: RequestWithAuth, res: Response, next: NextFunction): void => {
if (req.token === undefined || req.token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
if (req.token.account !== systemAccountUuid && req.token.extra?.admin !== 'true') {
res.status(401).json({ message: 'Admins only' }).end()
return
}
next()
}
export const withLoginInfo = (req: RequestWithAuth, res: Response, next: NextFunction): void => {
void withLoginInfoAsync(req, res, next)
}
const withLoginInfoAsync = async (req: RequestWithAuth, res: Response, next: NextFunction): Promise<void> => {
if (req.token === undefined || req.token == null) {
res.status(401).json({ message: 'Token error' }).end()
return
}
const accountClient = getAccountClient(req.headers.authorization?.split(' ')[1])
const loginInfo = await accountClient.getLoginInfoByToken()
if (loginInfo == null) {View on GitHub (pinned to 63e28dc964)
Solutions
- Obtain a token issued to the system account or one carrying extra.admin='true'
- Verify the account service issues the admin claim for this user and re-login to refresh the token
- Check that systemAccountUuid in this pod's config matches the account UUID used to mint admin tokens (env var/config check)
- If the caller should be admin, grant the admin flag on the account and issue a new token
Defensive patterns
Strategy: type-guard
Validate before calling
function isAdminToken(token: { account: string; extra?: { admin?: string } }, systemAccountUuid: string): boolean {
return token.account === systemAccountUuid || token.extra?.admin === 'true'
}
// decode the JWT client-side before calling an admin endpoint
const claims = JSON.parse(atob(token.split('.')[1]))
if (!isAdminToken(claims, SYSTEM_ACCOUNT_UUID)) skipAdminCall() Type guard
function isAdminClaims(c: { account?: string; extra?: { admin?: string } } | null, systemAccountUuid: string): c is { account: string; extra: { admin: 'true' } } {
return c != null && (c.account === systemAccountUuid || c.extra?.admin === 'true')
} Try / catch
try {
const res = await callAdminApi()
} catch (err) {
if (err.response?.status === 401 && err.response.data?.message === 'Admins only') {
// surface 'requires admin privileges' to the user; do not retry
}
} Prevention
- Hide admin-only UI/actions unless the decoded token actually has the admin claim
- Re-issue tokens after granting/revoking admin flags — claims are baked into the JWT
- Keep systemAccountUuid config in sync across environments
- Never call admin endpoints with end-user tokens; use a service token
When it happens
Trigger: Any authenticated non-admin user calling an endpoint protected by withAdmin; or a legit admin whose token was issued without the extra.admin='true' claim.
Common situations: A regular workspace user hitting an internal admin API; an admin whose JWT was minted by a login flow that does not set extra.admin; stale tokens issued before the admin claim was added to the account service; environment mismatch where systemAccountUuid differs from the account in the token (config drift across pods).
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/294991f29ebc9927.
Report an issue: GitHub.