feat: account linking for magic link + Google, last login method hint
- Move account linking config out of Google conditional so it's always active - Trust both 'google' and 'email' providers for automatic account linking - Add lastLoginMethod plugin to track how users last signed in - Show "Last signed in with Google/email link" hint in sign-in dialog Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
a0ac904dfc
commit
6f7613818b
@@ -36,6 +36,11 @@ function GoogleIcon({ className }: { className?: string }) {
|
||||
/**
|
||||
* SignInDialog - Authentication dialog with Google OAuth and magic link
|
||||
*/
|
||||
const LOGIN_METHOD_LABELS: Record<string, string> = {
|
||||
google: 'Google',
|
||||
'magic-link': 'email link',
|
||||
}
|
||||
|
||||
export function SignInDialog({ open, onOpenChange }: SignInDialogProps) {
|
||||
const [email, setEmail] = useState('')
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
@@ -43,6 +48,9 @@ export function SignInDialog({ open, onOpenChange }: SignInDialogProps) {
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [success, setSuccess] = useState(false)
|
||||
|
||||
const lastMethod = authClient.getLastUsedLoginMethod?.()
|
||||
const lastMethodLabel = lastMethod ? LOGIN_METHOD_LABELS[lastMethod] ?? lastMethod : null
|
||||
|
||||
const handleGoogleSignIn = async () => {
|
||||
setError(null)
|
||||
setIsGoogleLoading(true)
|
||||
@@ -134,6 +142,12 @@ export function SignInDialog({ open, onOpenChange }: SignInDialogProps) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
{lastMethodLabel && (
|
||||
<p className="text-center text-muted-foreground text-xs">
|
||||
Last signed in with {lastMethodLabel}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Google Sign-In */}
|
||||
<button
|
||||
className="flex w-full items-center justify-center gap-2 rounded-md border border-input bg-background px-4 py-2.5 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground disabled:opacity-50"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { magicLinkClient } from 'better-auth/client/plugins'
|
||||
import { lastLoginMethodClient, magicLinkClient } from 'better-auth/client/plugins'
|
||||
import { createAuthClient } from 'better-auth/react'
|
||||
|
||||
/**
|
||||
@@ -45,7 +45,7 @@ function getAuthURL(): string {
|
||||
*/
|
||||
export const authClient = createAuthClient({
|
||||
baseURL: getAuthURL(),
|
||||
plugins: [magicLinkClient()],
|
||||
plugins: [magicLinkClient(), lastLoginMethodClient()],
|
||||
})
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ import { schema } from '@pascal-app/db'
|
||||
import type { BetterAuthOptions } from 'better-auth'
|
||||
import { betterAuth } from 'better-auth'
|
||||
import { drizzleAdapter } from 'better-auth/adapters/drizzle'
|
||||
import { magicLink } from 'better-auth/plugins'
|
||||
import { lastLoginMethod, magicLink } from 'better-auth/plugins'
|
||||
|
||||
export interface SendMagicLinkParams {
|
||||
email: string
|
||||
@@ -61,6 +61,13 @@ export function createAuth(config: AuthConfig): ReturnType<typeof betterAuth> {
|
||||
},
|
||||
},
|
||||
},
|
||||
// Account linking — always enabled so magic link + Google users can share accounts
|
||||
account: {
|
||||
accountLinking: {
|
||||
enabled: true,
|
||||
trustedProviders: ['google', 'email'],
|
||||
},
|
||||
},
|
||||
// Google OAuth provider (only enabled when credentials are provided)
|
||||
...(config.googleClientId &&
|
||||
config.googleClientSecret && {
|
||||
@@ -70,15 +77,11 @@ export function createAuth(config: AuthConfig): ReturnType<typeof betterAuth> {
|
||||
clientSecret: config.googleClientSecret,
|
||||
},
|
||||
},
|
||||
account: {
|
||||
accountLinking: {
|
||||
enabled: true,
|
||||
trustedProviders: ['google'],
|
||||
},
|
||||
},
|
||||
}),
|
||||
plugins: [
|
||||
...(config.additionalPlugins ?? []),
|
||||
// Track which login method was last used (e.g., "google", "magic-link")
|
||||
lastLoginMethod(),
|
||||
// Magic link authentication
|
||||
...(config.sendMagicLink
|
||||
? [
|
||||
|
||||
Reference in New Issue
Block a user