gts-x / src /lib /auth.ts
JAMES HAN
Initial commit — GTS Modern subtitle converter
dff41a8
Raw
History Blame Contribute Delete
2.57 kB
import { betterAuth } from 'better-auth';
import { getStringLiteralChecker } from './utils';
const betterAuthUrl = process.env.NEXT_PUBLIC_BETTER_AUTH_URL!;
const permissions = ['GeneralSettings.read', 'GeneralSettings.write'] as const;
export type Permission = (typeof permissions)[number];
export const isPermission = getStringLiteralChecker(permissions);
const roleToPerm = new Map<string, readonly Permission[]>([
['TestRole1', []],
['TestRole2', ['GeneralSettings.read']],
['User', ['GeneralSettings.read']],
['PowerUser', ['GeneralSettings.read', 'GeneralSettings.write']],
]);
export const auth = betterAuth({
secret: process.env.BETTER_AUTH_SECRET!,
baseURL: betterAuthUrl,
socialProviders: {
microsoft: {
clientId: process.env.MICROSOFT_CLIENT_ID!,
clientSecret: process.env.MICROSOFT_CLIENT_SECRET!,
tenantId: process.env.MICROSOFT_TENANT_ID!,
enabled: true,
// Entra test users comes without email field populated in profile (this breaks better-auth)
// https://www.better-auth.com/docs/errors/email_not_found
// So we map the profile to ensure email is always set
// This is likely needed only for test purposes
// Problem: any extra attributes returned from this function are not available in custom session
// https://github.com/better-auth/better-auth/discussions/3290 "Map additional fields by using mapProfileToUser in OAuth"
mapProfileToUser: (profile) => {
const userRoles = profile.roles || [];
const userPerms = [
...new Set(userRoles.flatMap((role) => roleToPerm.get(role) || [])),
];
return {
id: profile.id || profile.sub,
email:
profile.preferred_username ||
profile.userPrincipalName ||
profile.mail ||
profile.email ||
profile.oid ||
`${profile.id}@placeholder.local`,
name: profile.displayName || profile.name,
image: profile.picture,
emailVerified: true,
roles: userRoles,
permissions: userPerms,
};
},
},
},
user: {
additionalFields: {
roles: {
type: 'string[]',
},
permissions: {
type: 'string[]',
},
},
},
session: {
expiresIn: 60 * 60 * 24, // 24 hours
updateAge: 60 * 60 * 1, // update every 1 hour
cookieCache: {
enabled: true,
maxAge: 60 * 5, // 5 minutes
},
cookieOptions: {
sameSite: 'lax', // Important for OAuth redirects
},
},
});