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

  1. Obtain a token issued to the system account or one carrying extra.admin='true'
  2. Verify the account service issues the admin claim for this user and re-login to refresh the token
  3. Check that systemAccountUuid in this pod's config matches the account UUID used to mint admin tokens (env var/config check)
  4. 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

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.