add: oidc,passkey,disable email/password,sign-up

This commit is contained in:
Théo LAGACHE
2026-02-13 16:48:13 +01:00
parent 7ab213e5e4
commit 3bf731055f
29 changed files with 6199 additions and 525 deletions
@@ -15,9 +15,11 @@ import {PasswordInput} from "@/components/ui/password-input";
export type loginFormProps = {
defaultValues?: LoginType;
isPasskeyEnabled?: boolean;
};
export const LoginForm = (props: loginFormProps) => {
const {isPasskeyEnabled = false} = props;
const [urlParams, setUrlParams] = useState<URLSearchParams>();
@@ -106,7 +108,7 @@ export const LoginForm = (props: loginFormProps) => {
</div>
</div>
<FormControl>
<PasswordInput autoComplete="current-password webauthn"
<PasswordInput autoComplete={isPasskeyEnabled ? "current-password webauthn" : "current-password"}
placeholder={"Enter your password"} {...field} />
</FormControl>
<FormMessage/>
+53 -35
View File
@@ -1,29 +1,52 @@
"use client";
import React, { useState } from "react";
import { useState } from "react";
import { Button } from "@/components/ui/button";
import { authClient } from "@/lib/auth/auth-client";
import { authClient, passkey } from "@/lib/auth/auth-client";
import { Loader2 } from "lucide-react";
import { toast } from "sonner";
import {AuthProviderConfig} from "../../../../portabase.config";
import {Icon} from "@iconify/react";
import { Icon } from "@iconify/react";
import { AuthProviderConfig } from "@/lib/auth/config";
import Image from "next/image";
import { useRouter } from "next/navigation";
export function SocialAuthButtons({ providers }: { providers: AuthProviderConfig[] }) {
const socialProviders = providers.filter(p => p.isActive && !p.isManual);
const socialProviders = providers.filter((p) => p.isActive && p.type !== "credential");
const router = useRouter();
const [isLoading, setIsLoading] = useState<string | null>(null);
const handleSocialSignIn = async (providerId: string) => {
setIsLoading(providerId);
const handleSocialSignIn = async (provider: AuthProviderConfig) => {
setIsLoading(provider.id);
try {
const { error } = await authClient.signIn.social({
provider: providerId as "google" | "github",
callbackURL: "/dashboard",
});
if (error) {
toast.error("An error occurred while signing in with the provider. Please try again.");
let result;
if (provider.id === "passkey") {
result = await authClient.signIn.passkey({
fetchOptions: {
onSuccess() {
router.push("/dashboard");
},
onError() {
toast.error("An error occurred during passkey authentication. Please try again.");
},
},
});
} else if (provider.type === "sso") {
result = await authClient.signIn.sso({
providerId: provider.id,
providerType: "oidc",
callbackURL: "/dashboard",
});
} else {
result = await authClient.signIn.social({
provider: provider.id as "google" | "github",
callbackURL: "/dashboard",
});
}
if (result?.error) {
toast.error("An error occurred while signing in with the provider. Please try again.");
} else if (provider.id !== "passkey") {
toast.success("Redirecting to provider...");
}
} catch (err) {
@@ -38,29 +61,24 @@ export function SocialAuthButtons({ providers }: { providers: AuthProviderConfig
return (
<div className="flex flex-col gap-2 w-full">
{socialProviders.map((provider) => (
<Button key={provider.id} variant="outline" className="w-full gap-2" onClick={() => handleSocialSignIn(provider.id)} disabled={!!isLoading}>
{isLoading === provider.id ? <Loader2 className="h-4 w-4 animate-spin" /> :
<Icon icon={provider.icon} className="h-4 w-4"/>
}
<span>{PROVIDERS_TEXT[provider.id].title}</span>
<Button key={provider.id} variant="outline" className="w-full gap-2" onClick={() => handleSocialSignIn(provider)} disabled={!!isLoading}>
{isLoading === provider.id ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : provider.icon.startsWith("/") || provider.icon.startsWith("http") ? (
<Image
src={provider.icon}
alt={provider.id || "icon"}
width={16}
height={16}
className="h-4 w-4"
unoptimized={provider.icon.startsWith("http")}
/>
) : (
<Icon icon={provider.icon} className="h-4 w-4" />
)}
<span>{provider.title || provider.name}</span>
</Button>
))}
</div>
);
}
const PROVIDERS_TEXT = {
credential: {
title: "Password",
description: "Use your email address and password to sign in."
},
google: {
title: "Google",
description: "Sign in with your Google account."
},
github: {
title: "GitHub",
description: "Sign in with your GitHub account."
}
}