RocketChat/Rocket.Chat · error · Meteor.Error

not-authorized

not-authorized

Error message

Not Authorized

What it means

Thrown by generatePersonalAccessTokenOfUser when the target user lacks the 'create-personal-access-tokens' permission. This is the programmatic/internal API guard (the function is called with an explicit userId, e.g. by an admin or another server-side caller) distinct from the login check. Without the permission the user cannot mint personal access tokens.

Source

Thrown at apps/meteor/imports/personal-access-tokens/server/api/methods/generateToken.ts:26

import { twoFactorRequired } from '../../../../../server/lib/2fa/twoFactorRequired';
declare module '@rocket.chat/ddp-client' {
	// eslint-disable-next-line @typescript-eslint/naming-convention
	interface ServerMethods {
		'personalAccessTokens:generateToken'(params: { tokenName: string; bypassTwoFactor: boolean }): Promise<string>;
	}
}

export const generatePersonalAccessTokenOfUser = async ({
	bypassTwoFactor,
	tokenName,
	userId,
}: {
	tokenName: string;
	userId: string;
	bypassTwoFactor: boolean;
}): Promise<string> => {
	if (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {
		throw new Meteor.Error('not-authorized', 'Not Authorized', {
			method: 'personalAccessTokens:generateToken',
		});
	}

	const token = Random.secret();
	const tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({
		userId,
		tokenName,
	});
	if (tokenExist) {
		throw new Meteor.Error('error-token-already-exists', 'A token with this name already exists', {
			method: 'personalAccessTokens:generateToken',
		});
	}

	await Users.addPersonalAccessTokenToUser({
		userId,
		loginTokenObject: {

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Grant the 'create-personal-access-tokens' permission to the user's role in the administration UI.
  2. Confirm you are passing the correct userId (not the caller's id) to the function.
  3. If the caller is an admin acting on behalf of a user, ensure that user role has the permission.
  4. Catch the error and return a 403/permission-denied response to the client.
Defensive patterns

Strategy: validation

Validate before calling

async function canCreateTokens(userId: string): Promise<boolean> {
  return hasPermissionAsync(userId, 'create-personal-access-tokens');
}

Try / catch

try {
  await generatePersonalAccessTokenOfUser({ userId, tokenName, bypassTwoFactor });
} catch (e) {
  if (e.error === 'not-authorized') {
    // return 403 and instruct admin to grant the permission
  } else throw e;
}

Prevention

When it happens

Trigger: Calling generatePersonalAccessTokenOfUser({ userId, tokenName, bypassTwoFactor }) for a user whose roles do not include 'create-personal-access-tokens'; calling on behalf of a user whose permission was revoked.

Common situations: Admin removed the permission after a security review; a custom role missing the permission; integration calling the internal API for a user that was demoted; new install where the default role policies were changed.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12). Data as JSON: /api/errors/c19120cd0bab3150. Report an issue: GitHub.