1+ import type { UserRecord } from 'firebase-admin/auth' ;
2+ import { getAuth } from 'firebase-admin/auth' ;
3+ import type { AppConfigInput } from 'nuxt/schema' ;
4+ import type { H3Event } from 'h3' ;
5+
6+ export async function getOTP ( email : string , event : H3Event ) {
7+ const config = useAppConfig ( event ) ;
8+ const user = await getUserByEmail ( email ) ;
9+ return generateOTP ( user , config ) ;
10+ }
11+
12+ export async function authOTP ( email : string , otp : string , event : H3Event ) {
13+ const config = useAppConfig ( event ) ;
14+ const user = await getAuth ( ) . getUserByEmail ( email ) ;
15+ await checkOtp ( user , otp , config ) ;
16+
17+ await getAuth ( ) . updateUser ( user . uid , {
18+ emailVerified : true ,
19+ } ) ;
20+ const token = await getAuth ( ) . createCustomToken ( user . uid ) ;
21+
22+ return { token } ;
23+ } ;
24+
25+ // eslint-disable-next-line complexity
26+ async function checkOtp ( user : UserRecord , otp : string , config : AppConfigInput ) {
27+ const doc = await documentsCollection (
28+ config . firebase ?. authCollection || 'auth' ,
29+ ) . doc ( user . uid ) . get ( ) ;
30+ if ( ! doc . exists ) throw createError ( {
31+ status : 404 ,
32+ statusMessage : 'OTP not found' ,
33+ } ) ;
34+
35+ const data = doc . data ( ) ;
36+
37+ if ( ! data ) throw createError ( {
38+ status : 404 ,
39+ statusMessage : 'OTP data not found' ,
40+ } ) ;
41+
42+ if ( Number ( data . otp ) !== Number ( otp ) || new Date ( data . ttl ) . getTime ( ) < Date . now ( ) ) {
43+ throw createError ( {
44+ status : 401 ,
45+ statusMessage : 'Invalid OTP' ,
46+ } ) ;
47+ }
48+ await doc . ref . delete ( ) ;
49+ }
50+
51+ async function getUserByEmail ( email : string ) {
52+ const user = await getAuth ( ) . getUserByEmail ( email ) . catch ( ( ) => null ) ;
53+ if ( user ) return user ;
54+ return getAuth ( ) . createUser ( {
55+ email,
56+ emailVerified : false ,
57+ } ) ;
58+ }
59+
60+ // eslint-disable-next-line complexity
61+ async function generateOTP ( user : UserRecord , config : AppConfigInput ) {
62+ const otp = Math . floor ( 100000 + Math . random ( ) * 900000 ) ;
63+ await documentsCollection ( config . firebase ?. authCollection || 'auth' ) . doc ( user . uid ) . set ( {
64+ otp,
65+ ttl : Date . now ( ) + ( config . firebase ?. otpTTL || 1000 * 60 * 5 ) ,
66+ } ) ;
67+ return otp ;
68+ }
0 commit comments