BA
Better Auth•4w ago
Zamiel

Does anyone have a good example of how authClient.admin.hasPermission works?

I've tried everything, searching, using AI, but nothing makes it work in my code. How should this be used correctly? Could some good soul give me an example of a complete configuration + example of use?
Solution:
You can't force cast as BetterAuthOptions as that will break inference in your auth config.
Jump to solution
6 Replies
Ping
Ping•4w ago
This simply checks if the provided user based on the user-id contains those set of permissions, this was copied from our docs: (but modified a little to make easier to understand)
const { data, error } = await authClient.admin.hasPermission({
userId: "user-id",
permission: { "project": ["create", "update"] }
});
const { data, error } = await authClient.admin.hasPermission({
userId: "user-id",
permission: { "project": ["create", "update"] }
});
Is the docs missing something for you?
Zamiel
ZamielOP•4w ago
I can only use it like this on the server, besides that I always have these typescript errors, are they normal?
Property 'userHasPermission' does not exist on type 'InferAPI<{ ok: { <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0?: ({ body?: undefined; } & { method?: "GET" | undefined; } & { query?: Record<string, any> | undefined; } & { params?: Record<string, any> | undefined; } & { ...; } & { ...; } & { ...; } & { ...; }) | undefined): ...'.ts(2339)
any
Property 'userHasPermission' does not exist on type 'InferAPI<{ ok: { <AsResponse extends boolean = false, ReturnHeaders extends boolean = false>(inputCtx_0?: ({ body?: undefined; } & { method?: "GET" | undefined; } & { query?: Record<string, any> | undefined; } & { params?: Record<string, any> | undefined; } & { ...; } & { ...; } & { ...; } & { ...; }) | undefined): ...'.ts(2339)
any
"better-auth": "1.3" typescript 5.9.2 @Max
No description
Ping
Ping•4w ago
Can you show me your auth config?
Zamiel
ZamielOP•4w ago
import { createAuthClient } from "better-auth/react";
import { adminClient, usernameClient, organizationClient, inferOrgAdditionalFields } from "better-auth/client/plugins";
import { env } from "@/lib/env";
import { ac, roles } from "@/lib/auth/permissions";
import { stripeClient } from "@better-auth/stripe/client";
import { auth } from "./auth";

export const authClient = createAuthClient({
baseURL: env.NEXT_PUBLIC_APP_URL,
plugins: [
usernameClient(),
adminClient({
ac,
roles,
}),
stripeClient({
subscription: true
}),
organizationClient({
schema: inferOrgAdditionalFields<typeof auth>(),
ac,
roles,
teams: {
enabled: true
}
}),
],
})

export const {
signIn,
signOut,
signUp,
useSession,
admin,
organization,
} = authClient;

export type Auth = typeof auth
export type AuthClient = typeof authClient
export type Organization = typeof authClient.organization
export type ActiveOrganization = typeof authClient.$Infer.ActiveOrganization;
export type Member = typeof authClient.$Infer.Member
export type Invitation = typeof authClient.$Infer.Invitation
export type Team = typeof authClient.$Infer.Team

export async function getJWT(): Promise<string | null> {
try {
const response = await fetch('/api/auth/token', {
credentials: 'include'
});

if (!response.ok) {
return null;
}

const data = await response.json();
return data.token;
} catch (error) {
console.error('Error getting JWT:', error);
return null;
}
}
import { createAuthClient } from "better-auth/react";
import { adminClient, usernameClient, organizationClient, inferOrgAdditionalFields } from "better-auth/client/plugins";
import { env } from "@/lib/env";
import { ac, roles } from "@/lib/auth/permissions";
import { stripeClient } from "@better-auth/stripe/client";
import { auth } from "./auth";

export const authClient = createAuthClient({
baseURL: env.NEXT_PUBLIC_APP_URL,
plugins: [
usernameClient(),
adminClient({
ac,
roles,
}),
stripeClient({
subscription: true
}),
organizationClient({
schema: inferOrgAdditionalFields<typeof auth>(),
ac,
roles,
teams: {
enabled: true
}
}),
],
})

export const {
signIn,
signOut,
signUp,
useSession,
admin,
organization,
} = authClient;

export type Auth = typeof auth
export type AuthClient = typeof authClient
export type Organization = typeof authClient.organization
export type ActiveOrganization = typeof authClient.$Infer.ActiveOrganization;
export type Member = typeof authClient.$Infer.Member
export type Invitation = typeof authClient.$Infer.Invitation
export type Team = typeof authClient.$Infer.Team

export async function getJWT(): Promise<string | null> {
try {
const response = await fetch('/api/auth/token', {
credentials: 'include'
});

if (!response.ok) {
return null;
}

const data = await response.json();
return data.token;
} catch (error) {
console.error('Error getting JWT:', error);
return null;
}
}
Solution
Ping
Ping•4w ago
You can't force cast as BetterAuthOptions as that will break inference in your auth config.
Zamiel
ZamielOP•4w ago
Ohhh, that was really it. Thank you! 🥰

Did you find this page helpful?