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
- Grant the 'create-personal-access-tokens' permission to the user's role in the administration UI.
- Confirm you are passing the correct userId (not the caller's id) to the function.
- If the caller is an admin acting on behalf of a user, ensure that user role has the permission.
- 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
- Verify the user's role includes 'create-personal-access-tokens' before offering the token UI.
- Audit permission grants after role changes.
- Return clear 403 messages to the client when permission is missing.
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.