84 lines
2.0 KiB
TypeScript
84 lines
2.0 KiB
TypeScript
import { jwtDecode } from 'jwt-decode'
|
|
import { getAuth, signInWithPopup, GoogleAuthProvider, signOut, onAuthStateChanged } from 'firebase/auth'
|
|
|
|
interface User {
|
|
id: string
|
|
email: string
|
|
username: string
|
|
role?: string
|
|
}
|
|
|
|
export const useAuth = () => {
|
|
const token = useCookie<string | null>('xflow_token', {
|
|
maxAge: 60 * 60 * 24 * 7,
|
|
sameSite: 'strict'
|
|
})
|
|
|
|
const user = computed<User | null>(() => {
|
|
if (!token.value) return null
|
|
try {
|
|
return jwtDecode<User>(token.value)
|
|
} catch {
|
|
return null
|
|
}
|
|
})
|
|
|
|
const isAuthenticated = computed(() => !!token.value && !!user.value)
|
|
const isAdmin = computed(() => user.value?.role === 'admin')
|
|
|
|
const googleSignIn = async () => {
|
|
const auth = getAuth()
|
|
const provider = new GoogleAuthProvider()
|
|
const result = await signInWithPopup(auth, provider)
|
|
const idToken = await result.user.getIdToken()
|
|
|
|
const res = await $fetch<{ token: string; user: User }>('/api/auth/google', {
|
|
method: 'POST',
|
|
body: { idToken }
|
|
})
|
|
|
|
token.value = res.token
|
|
await navigateTo('/')
|
|
}
|
|
|
|
const logout = async () => {
|
|
const auth = getAuth()
|
|
await signOut(auth)
|
|
token.value = null
|
|
navigateTo('/login')
|
|
}
|
|
|
|
const initAuth = () => {
|
|
const auth = getAuth()
|
|
onAuthStateChanged(auth, async (firebaseUser) => {
|
|
// If user is authenticated in Firebase but we lost our backend token, try to restore
|
|
if (firebaseUser && !token.value) {
|
|
try {
|
|
const idToken = await firebaseUser.getIdToken()
|
|
const res = await $fetch<{ token: string; user: User }>('/api/auth/google', {
|
|
method: 'POST',
|
|
body: { idToken }
|
|
})
|
|
token.value = res.token
|
|
|
|
if (useRoute().path === '/login') {
|
|
navigateTo('/')
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to restore backend auth from Firebase', e)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
return {
|
|
token,
|
|
user,
|
|
isAuthenticated,
|
|
isAdmin,
|
|
googleSignIn,
|
|
logout,
|
|
initAuth
|
|
}
|
|
}
|