@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
3 lines (2 loc) • 6.84 kB
JavaScript
;Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react"),Q=require("./use-auth.cjs"),J=require("../provider/config-provider.cjs"),V={totp:{name:"Authenticator App",description:"Use an authenticator app like Google Authenticator or Authy",icon:"📱",setupSteps:["Install an authenticator app on your phone","Scan the QR code or enter the secret key","Enter the 6-digit code from your app"]},sms:{name:"SMS",description:"Receive codes via text message",icon:"💬",setupSteps:["Enter your phone number","Wait for the verification code","Enter the code to confirm"]},email:{name:"Email",description:"Receive codes via email",icon:"✉️",setupSteps:["Confirm your email address","Wait for the verification code","Enter the code to confirm"]},webauthn:{name:"Security Key",description:"Use a hardware security key or biometric authentication",icon:"🔐",setupSteps:["Insert your security key or prepare biometric authentication","Follow your browser's authentication prompts","Confirm the registration"]},backup_codes:{name:"Backup Codes",description:"Single-use codes for emergency access",icon:"🔢",setupSteps:["Save these codes in a secure location","Each code can only be used once","Generate new codes when running low"]}};function b(){const{user:n,session:y,reload:c,userType:p,sdk:t}=Q.useAuth(),{apiUrl:f,publishableKey:M,features:i}=J.useConfig(),[u,S]=s.useState([]),[A,C]=s.useState([]),[T,a]=s.useState(!1),[q,l]=s.useState(null),d=s.useMemo(()=>i.mfa,[i.mfa]),o=s.useCallback(e=>{const r={code:e.code||"UNKNOWN_ERROR",message:e.message||"An unknown error occurred",details:e.details,field:e.field};throw l(r),r},[]),h=s.useCallback(async()=>{if(!(!t.user||!n||!d))try{a(!0),l(null);const e=await t.user.getMFAMethods({orgId:t.user.getOrganizationId(),userId:t.user.getUserData()});if(S(e.data||[]),n.mfaEnabled)try{const r=await t.user.getBackupCodes();C(r.codes||[])}catch(r){console.warn("Could not load backup codes:",r)}}catch(e){console.error("Failed to load MFA data:",e),l({code:"MFA_LOAD_FAILED",message:"Failed to load MFA data"})}finally{a(!1)}},[t.user,n,d]);s.useEffect(()=>{h()},[h]);const O=s.useCallback(async()=>{if(!t.user)throw new Error("User not authenticated");if(!d)throw new Error("MFA not available");try{a(!0),l(null);const e={method:"totp"},r=await t.user.setupMFA(e);return{method:"totp",qrCode:r.qrCode,secret:r.secret,backupCodes:r.backupCodes,verificationRequired:!0}}catch(e){return o(e)}finally{a(!1)}},[t.user,d,o]),U=s.useCallback(async e=>{if(!t.user)throw new Error("User not authenticated");if(!d)throw new Error("MFA not available");try{a(!0),l(null);const r={method:"sms",phoneNumber:e},w=await t.user.setupMFA(r);return{method:"sms",verificationRequired:!0}}catch(r){return o(r)}finally{a(!1)}},[t.user,d,o]),B=s.useCallback(async e=>{if(!t.user)throw new Error("User not authenticated");if(!d)throw new Error("MFA not available");try{a(!0),l(null);const r={method:"email",email:e||n?.primaryEmailAddress},w=await t.user.setupMFA(r);return{method:"email",verificationRequired:!0}}catch(r){return o(r)}finally{a(!1)}},[t.user,n,d,o]),P=s.useCallback(async()=>{if(!d)throw new Error("MFA not available");try{a(!0),l(null);const e={method:"webauthn"};return{method:"webauthn",challenge:(await t.auth.setupMFA(e)).challenge,verificationRequired:!0}}catch(e){return o(e)}finally{a(!1)}},[t.user,d,o]),I=s.useCallback(async(e,r,w)=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null);const m={method:e,code:r,methodId:w,generateBackupCodes:!1},R=await t.user.verifyMFASetup(m);return await h(),await c(),R.method}catch(m){return o(m)}finally{a(!1)}},[t.user,h,c,o]),L=s.useCallback(async(e,r,w)=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null);const m={method:e,code:r,mfaToken:w,context:"login"};return await t.auth.verifyMFA(m)}catch(m){return o(m)}finally{a(!1)}},[t.user,o]),_=s.useCallback(async e=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null),await t.user.removeMFAMethod(e),await h(),await c()}catch(r){o(r)}finally{a(!1)}},[t.user,h,c,o]),N=s.useCallback(async e=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null),await t.user.setPrimaryMFAMethod(e),await h()}catch(r){o(r)}finally{a(!1)}},[t.user,h,o]),D=s.useCallback(async()=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null);const e=await t.user.regenerateMFABackupCodes();return C(e.codes),e.codes}catch(e){return o(e)}finally{a(!1)}},[t.user,o]),W=s.useMemo(()=>n?.mfaEnabled||!1,[n]),G=s.useMemo(()=>!1,[]),K=s.useMemo(()=>u.find(e=>e.isPrimary)||null,[u]),k=s.useMemo(()=>u.some(e=>e.type==="totp"),[u]),g=s.useMemo(()=>u.some(e=>e.type==="sms"),[u]),F=s.useMemo(()=>u.some(e=>e.type==="email"),[u]),v=s.useMemo(()=>u.some(e=>e.type==="webauthn"),[u]),E=s.useMemo(()=>A.length>0,[A]),x=s.useMemo(()=>{const e=[];return k&&e.push("totp"),g&&e.push("sms"),F&&e.push("email"),v&&e.push("webauthn"),E&&e.push("backup_codes"),e},[k,g,F,v,E]),H=s.useCallback(async()=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null),await t.user.disableMFA(),S([]),C([]),await c()}catch(e){o(e)}finally{a(!1)}},[t.user,c,o]),j=s.useCallback(async()=>{if(!t.user)throw new Error("User not authenticated");try{a(!0),l(null),await t.user.enableMFA(),await c()}catch(e){o(e)}finally{a(!1)}},[t.user,c,o]),z=s.useCallback(async()=>{await h()},[h]);return{mfaMethods:u,isEnabled:W,isRequired:G,primaryMethod:K,backupCodes:A,isLoaded:!!n&&d,isLoading:T,error:q,setupTOTP:O,setupSMS:U,setupEmail:B,setupWebAuthn:P,verifySetup:I,verifyMFA:L,removeMFAMethod:_,setPrimaryMethod:N,regenerateBackupCodes:D,hasTOTP:k,hasSMS:g,hasEmail:F,hasWebAuthn:v,hasBackupCodes:E,availableMethods:x,disable:H,enable:j,refreshMethods:z}}function X(){const{setupTOTP:n,verifySetup:y,hasTOTP:c,mfaMethods:p,removeMFAMethod:t,isLoading:f,error:M}=b(),i=s.useMemo(()=>p.find(u=>u.type==="totp"),[p]);return{isEnabled:c,method:i,setup:n,verify:u=>y("totp",u),remove:i?()=>t(i.id):void 0,isLoading:f,error:M}}function Y(){const{setupSMS:n,verifySetup:y,hasSMS:c,mfaMethods:p,removeMFAMethod:t,isLoading:f,error:M}=b(),i=s.useMemo(()=>p.find(u=>u.type==="sms"),[p]);return{isEnabled:c,method:i,setup:n,verify:u=>y("sms",u),remove:i?()=>t(i.id):void 0,phoneNumber:i?.phoneNumber||null,isLoading:f,error:M}}function Z(){const{backupCodes:n,regenerateBackupCodes:y,hasBackupCodes:c,isLoading:p,error:t}=b(),f=s.useMemo(()=>n.filter(i=>!i.used),[n]),M=s.useMemo(()=>n.filter(i=>i.used),[n]);return{codes:n,unusedCodes:f,usedCodes:M,hasBackupCodes:c,regenerate:y,remainingCodes:f.length,totalCodes:n.length,isRunningLow:f.length<=2,isLoading:p,error:t}}exports.MFA_METHOD_CONFIGS=V;exports.useBackupCodes=Z;exports.useMFA=b;exports.useSMSMFA=Y;exports.useTOTP=X;
//# sourceMappingURL=use-mfa.cjs.map