LibreChat/packages/api/src/auth/openid.ts

63 lines
2 KiB
TypeScript
Raw Permalink Normal View History

import { logger } from '@librechat/data-schemas';
import { ErrorTypes } from 'librechat-data-provider';
import type { IUser, UserMethods } from '@librechat/data-schemas';
/**
* Finds or migrates a user for OpenID authentication
* @returns user object (with migration fields if needed), error message, and whether migration is needed
*/
export async function findOpenIDUser({
openidId,
findUser,
email,
idOnTheSource,
strategyName = 'openid',
}: {
openidId: string;
findUser: UserMethods['findUser'];
email?: string;
idOnTheSource?: string;
strategyName?: string;
}): Promise<{ user: IUser | null; error: string | null; migration: boolean }> {
const primaryConditions = [];
if (openidId && typeof openidId === 'string') {
primaryConditions.push({ openidId });
}
if (idOnTheSource && typeof idOnTheSource === 'string') {
primaryConditions.push({ idOnTheSource });
}
let user = null;
if (primaryConditions.length > 0) {
user = await findUser({ $or: primaryConditions });
}
if (!user && email) {
user = await findUser({ email });
logger.warn(
`[${strategyName}] user ${user ? 'found' : 'not found'} with email: ${email} for openidId: ${openidId}`,
);
// If user found by email, check if they're allowed to use OpenID provider
if (user && user.provider && user.provider !== 'openid') {
logger.warn(
`[${strategyName}] Attempted OpenID login by user ${user.email}, was registered with "${user.provider}" provider`,
);
return { user: null, error: ErrorTypes.AUTH_FAILED, migration: false };
}
// If user found by email but doesn't have openidId, prepare for migration
if (user && !user.openidId) {
logger.info(
`[${strategyName}] Preparing user ${user.email} for migration to OpenID with sub: ${openidId}`,
);
user.provider = 'openid';
user.openidId = openidId;
return { user, error: null, migration: true };
}
}
return { user, error: null, migration: false };
}