RocketChat/Rocket.Chat · error · Meteor.Error

not-authorized

not-authorized

Error message

Not Authorized

What it means

Thrown by removePersonalAccessTokenOfUser when the target user lacks the 'create-personal-access-tokens' permission. Despite the action being a removal, Rocket.Chat gates all personal-access-token operations behind this single permission, so a user without it cannot delete tokens either. This is the internal-API guard with an explicit userId.

Source

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

import { Meteor } from 'meteor/meteor';
import type { ServerMethods } from '@rocket.chat/ddp-client';
import { Users } from '@rocket.chat/models';

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

export const removePersonalAccessTokenOfUser = async (tokenName: string, userId: string): Promise<void> => {
	if (!(await hasPermissionAsync(userId, 'create-personal-access-tokens'))) {
		throw new Meteor.Error('not-authorized', 'Not Authorized', {
			method: 'personalAccessTokens:removeToken',
		});
	}
	const tokenExist = await Users.findPersonalAccessTokenByTokenNameAndUserId({
		userId,
		tokenName,
	});
	if (!tokenExist) {
		throw new Meteor.Error('error-token-does-not-exists', 'Token does not exist', {
			method: 'personalAccessTokens:removeToken',
		});
	}
	await Users.removePersonalAccessTokenOfUser({
		userId,
		loginTokenObject: {
			type: 'personalAccessToken',
			name: tokenName,
		},

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Grant the 'create-personal-access-tokens' permission to the user's role.
  2. Confirm you are operating on the intended userId.
  3. Return a 403 and ask an admin to adjust permissions.
  4. Document that removal requires the same permission as creation.
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

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

Prevention

When it happens

Trigger: Calling removePersonalAccessTokenOfUser(tokenName, userId) for a user whose role does not include 'create-personal-access-tokens'.

Common situations: Permission revoked after token creation; role downgrade; integration acting on behalf of a user without the permission.

Related errors


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