Call Admin routes with API key
So, I created a System user of role admin and then created an API key like this:
When trying to use the returned API Key to call the
Here is the example of how its being called:
I've tried getting a session from the API Key and it does work
But this does fail
const apiKey = await auth.api.createApiKey({
body: {
name: 'System',
userId: '01991763-29cc-7409-9136-98d127723df9',
rateLimitEnabled: false,
permissions: {
user: ['create','list','set-role','ban','impersonate','delete','set-password'],
session: ['list', 'revoke', 'delete'],
},
},
});
const apiKey = await auth.api.createApiKey({
body: {
name: 'System',
userId: '01991763-29cc-7409-9136-98d127723df9',
rateLimitEnabled: false,
permissions: {
user: ['create','list','set-role','ban','impersonate','delete','set-password'],
session: ['list', 'revoke', 'delete'],
},
},
});
setUserPassword or listUsers I get this error:
{
"type": "Error",
"message": "",
"stack": "APIError",
"status": "UNAUTHORIZED",
"headers": {},
"statusCode": 401,
"name": "APIError"
}
{
"type": "Error",
"message": "",
"stack": "APIError",
"status": "UNAUTHORIZED",
"headers": {},
"statusCode": 401,
"name": "APIError"
}
const data = await auth.api
.setUserPassword({
body: {
newPassword,
userId: user.userId,
},
headers: new Headers({
'x-api-key': env.BETTER_AUTH_SYSTEM_KEY,
}),
});
const list = await auth.api
.listUsers({
headers: new Headers({
'x-api-key': <apiKey>,
}),
query: {},
});
const data = await auth.api
.setUserPassword({
body: {
newPassword,
userId: user.userId,
},
headers: new Headers({
'x-api-key': env.BETTER_AUTH_SYSTEM_KEY,
}),
});
const list = await auth.api
.listUsers({
headers: new Headers({
'x-api-key': <apiKey>,
}),
query: {},
});
const session = await auth.api
.getSession({
headers: new Headers({
'x-api-key': <apiKey>,
}),
})
{
"user": {
"username": "system",
"role": "admin",
"id": "01991763-29cc-7409-9136-98d127723df9"
...
},
"session": {
"userId": "01991763-29cc-7409-9136-98d127723df9",
...
}
}
const session = await auth.api
.getSession({
headers: new Headers({
'x-api-key': <apiKey>,
}),
})
{
"user": {
"username": "system",
"role": "admin",
"id": "01991763-29cc-7409-9136-98d127723df9"
...
},
"session": {
"userId": "01991763-29cc-7409-9136-98d127723df9",
...
}
}
const permissionsCheck = await auth.api
.userHasPermission({
body: {
permission: {
user: ['set-password', 'list'],
},
},
headers: new Headers({
'x-api-key': <apiKey>,
}),
})
const permissionsCheck = await auth.api
.userHasPermission({
body: {
permission: {
user: ['set-password', 'list'],
},
},
headers: new Headers({
'x-api-key': <apiKey>,
}),
})
4 Replies
in the
createApiKey call, you need to pass user headersThanks! Just tested ths but I'm still getting the same error, any clues on what else could it be?
@Max any clues? 😬
Can you show me your auth config?
import { db } from '@tms/db/client';
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin, apiKey, customSession, username } from 'better-auth/plugins';
import { env } from './env';
import { uuid } from './utils/utils';
export const auth = betterAuth({
emailAndPassword: { enabled: true },
database: drizzleAdapter(db, {
provider: 'pg',
}),
logger: {
disabled: false,
level: 'debug',
},
trustedOrigins: [...env.CORS.split(',')],
plugins: [
username(),
admin({
adminUserIds: ['01991763-29cc-7409-9136-98d127723df9'],
adminRoles: ['admin', 'user'],
}),
apiKey({
apiKeyHeaders: ['x-api-key'],
}),
customSession(async ({ user, session }) => {
const profile = await db.query.profile.findFirst({
with: {
roles: {
columns: { name: true },
with: {
feature: {
columns: {
name: true,
},
},
},
},
},
where: {
userId: user.id,
},
});
if (!profile) {
throw new Error('Profile not found');
}
const roles = profile.roles.map(
(role) =>
`${role.feature?.name?.toLowerCase()}:${role.name.toLowerCase()}`
);
return {
...session,
user,
roles,
profileId: profile.id,
userType: profile.userType,
};
}),
],
advanced: {
database: {
generateId: () => uuid(),
},
},
});
import { db } from '@tms/db/client';
import { betterAuth } from 'better-auth';
import { drizzleAdapter } from 'better-auth/adapters/drizzle';
import { admin, apiKey, customSession, username } from 'better-auth/plugins';
import { env } from './env';
import { uuid } from './utils/utils';
export const auth = betterAuth({
emailAndPassword: { enabled: true },
database: drizzleAdapter(db, {
provider: 'pg',
}),
logger: {
disabled: false,
level: 'debug',
},
trustedOrigins: [...env.CORS.split(',')],
plugins: [
username(),
admin({
adminUserIds: ['01991763-29cc-7409-9136-98d127723df9'],
adminRoles: ['admin', 'user'],
}),
apiKey({
apiKeyHeaders: ['x-api-key'],
}),
customSession(async ({ user, session }) => {
const profile = await db.query.profile.findFirst({
with: {
roles: {
columns: { name: true },
with: {
feature: {
columns: {
name: true,
},
},
},
},
},
where: {
userId: user.id,
},
});
if (!profile) {
throw new Error('Profile not found');
}
const roles = profile.roles.map(
(role) =>
`${role.feature?.name?.toLowerCase()}:${role.name.toLowerCase()}`
);
return {
...session,
user,
roles,
profileId: profile.id,
userType: profile.userType,
};
}),
],
advanced: {
database: {
generateId: () => uuid(),
},
},
});