feat(auth): use password-only admin login

This commit is contained in:
Jesse_Chen
2026-07-27 20:40:55 +08:00
parent 6b13f96f9a
commit ee166ab5d3
7 changed files with 58 additions and 45 deletions
+8 -2
View File
@@ -14,6 +14,7 @@ export default async function LoginPage() {
const config = readIdentityConfig(process.env);
let provider = config.provider;
let passwordEnabled = false;
let passwordOnly = false;
if (isSelfHostedIdentityEnabled(process.env)) {
const selfHosted = readSelfHostedIdentityConfig(process.env);
const surface = resolveIdentitySurface(
@@ -21,9 +22,14 @@ export default async function LoginPage() {
selfHosted,
);
if (surface === "admin") provider = "self-hosted";
passwordEnabled = provider === "self-hosted" && surface === "user";
passwordEnabled = provider === "self-hosted";
passwordOnly = surface === "admin";
}
return (
<EmailOtpLogin provider={provider} passwordEnabled={passwordEnabled} />
<EmailOtpLogin
provider={provider}
passwordEnabled={passwordEnabled}
passwordOnly={passwordOnly}
/>
);
}
+5 -3
View File
@@ -36,11 +36,13 @@ function passwordError(password: string, confirmation: string): string {
export function EmailOtpLogin({
provider,
passwordEnabled = false,
passwordOnly = false,
}: {
provider: AuthProvider;
passwordEnabled?: boolean;
passwordOnly?: boolean;
}) {
const [mode, setMode] = useState<AuthMode>("otp");
const [mode, setMode] = useState<AuthMode>(passwordOnly ? "password" : "otp");
const [step, setStep] = useState<AuthStep>("email");
const [email, setEmail] = useState("");
const [token, setToken] = useState("");
@@ -52,9 +54,9 @@ export function EmailOtpLogin({
const canUsePassword = provider === "self-hosted" && passwordEnabled;
const showLoginNavigation =
canUsePassword && (mode === "otp" || mode === "password");
canUsePassword && !passwordOnly && (mode === "otp" || mode === "password");
const showBackToLogin =
canUsePassword && (mode === "register" || mode === "forgot");
canUsePassword && !passwordOnly && (mode === "register" || mode === "forgot");
function chooseMode(nextMode: AuthMode, nextNotice = "") {
setMode(nextMode);
+10 -12
View File
@@ -100,19 +100,17 @@ export function buildAuthOptions({
path: "/",
},
},
...(surface === "user"
? {
emailAndPassword: {
enabled: true,
disableSignUp: true,
minPasswordLength: 8,
maxPasswordLength: 128,
revokeSessionsOnPasswordReset: true,
},
}
: {}),
emailAndPassword: {
enabled: true,
disableSignUp: true,
minPasswordLength: 8,
maxPasswordLength: 128,
revokeSessionsOnPasswordReset: true,
},
plugins: [
emailOTP(createEmailOtpOptions(emailSender, secret, surface === "admin")),
...(surface === "user"
? [emailOTP(createEmailOtpOptions(emailSender, secret, false))]
: []),
admin({
defaultRole: "user",
adminRoles: ["admin"],