@nauth-toolkit/core 0.1.13 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/database-columns.d.ts +70 -0
- package/dist/adapters/database-columns.d.ts.map +1 -1
- package/dist/adapters/database-columns.js +76 -2
- package/dist/adapters/database-columns.js.map +1 -1
- package/dist/adapters/express.adapter.d.ts +66 -0
- package/dist/adapters/express.adapter.d.ts.map +1 -1
- package/dist/adapters/express.adapter.js +80 -0
- package/dist/adapters/express.adapter.js.map +1 -1
- package/dist/adapters/fastify.adapter.d.ts +42 -0
- package/dist/adapters/fastify.adapter.d.ts.map +1 -1
- package/dist/adapters/fastify.adapter.js +86 -0
- package/dist/adapters/fastify.adapter.js.map +1 -1
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +9 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/storage.factory.d.ts +107 -0
- package/dist/adapters/storage.factory.d.ts.map +1 -1
- package/dist/adapters/storage.factory.js +114 -0
- package/dist/adapters/storage.factory.js.map +1 -1
- package/dist/adapters.d.ts +8 -0
- package/dist/adapters.d.ts.map +1 -1
- package/dist/adapters.js +8 -0
- package/dist/adapters.js.map +1 -1
- package/dist/bootstrap.d.ts +82 -0
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +106 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/dto/admin-set-password.dto.d.ts +90 -0
- package/dist/dto/admin-set-password.dto.d.ts.map +1 -1
- package/dist/dto/admin-set-password.dto.js +91 -0
- package/dist/dto/admin-set-password.dto.js.map +1 -1
- package/dist/dto/auth-challenge.dto.d.ts +170 -0
- package/dist/dto/auth-challenge.dto.d.ts.map +1 -1
- package/dist/dto/auth-challenge.dto.js +170 -0
- package/dist/dto/auth-challenge.dto.js.map +1 -1
- package/dist/dto/auth-response.dto.d.ts +196 -0
- package/dist/dto/auth-response.dto.d.ts.map +1 -1
- package/dist/dto/auth-response.dto.js +149 -0
- package/dist/dto/auth-response.dto.js.map +1 -1
- package/dist/dto/challenge-response.dto.d.ts +155 -0
- package/dist/dto/challenge-response.dto.d.ts.map +1 -1
- package/dist/dto/challenge-response.dto.js +8 -0
- package/dist/dto/challenge-response.dto.js.map +1 -1
- package/dist/dto/change-password-request.dto.d.ts +35 -0
- package/dist/dto/change-password-request.dto.d.ts.map +1 -1
- package/dist/dto/change-password-request.dto.js +35 -0
- package/dist/dto/change-password-request.dto.js.map +1 -1
- package/dist/dto/change-password-response.dto.d.ts +25 -0
- package/dist/dto/change-password-response.dto.d.ts.map +1 -1
- package/dist/dto/change-password-response.dto.js +25 -0
- package/dist/dto/change-password-response.dto.js.map +1 -1
- package/dist/dto/change-password.dto.d.ts +45 -0
- package/dist/dto/change-password.dto.d.ts.map +1 -1
- package/dist/dto/change-password.dto.js +45 -0
- package/dist/dto/change-password.dto.js.map +1 -1
- package/dist/dto/confirm-forgot-password.dto.d.ts +59 -0
- package/dist/dto/confirm-forgot-password.dto.d.ts.map +1 -1
- package/dist/dto/confirm-forgot-password.dto.js +59 -0
- package/dist/dto/confirm-forgot-password.dto.js.map +1 -1
- package/dist/dto/error-response.dto.d.ts +103 -0
- package/dist/dto/error-response.dto.d.ts.map +1 -1
- package/dist/dto/error-response.dto.js +103 -0
- package/dist/dto/error-response.dto.js.map +1 -1
- package/dist/dto/forgot-password.dto.d.ts +58 -0
- package/dist/dto/forgot-password.dto.d.ts.map +1 -1
- package/dist/dto/forgot-password.dto.js +58 -0
- package/dist/dto/forgot-password.dto.js.map +1 -1
- package/dist/dto/get-available-methods.dto.d.ts +37 -0
- package/dist/dto/get-available-methods.dto.d.ts.map +1 -1
- package/dist/dto/get-available-methods.dto.js +37 -0
- package/dist/dto/get-available-methods.dto.js.map +1 -1
- package/dist/dto/get-challenge-data-response.dto.d.ts +24 -0
- package/dist/dto/get-challenge-data-response.dto.d.ts.map +1 -1
- package/dist/dto/get-challenge-data-response.dto.js +24 -0
- package/dist/dto/get-challenge-data-response.dto.js.map +1 -1
- package/dist/dto/get-challenge-data.dto.d.ts +46 -0
- package/dist/dto/get-challenge-data.dto.d.ts.map +1 -1
- package/dist/dto/get-challenge-data.dto.js +46 -0
- package/dist/dto/get-challenge-data.dto.js.map +1 -1
- package/dist/dto/get-client-info.dto.d.ts +74 -0
- package/dist/dto/get-client-info.dto.d.ts.map +1 -1
- package/dist/dto/get-client-info.dto.js +74 -0
- package/dist/dto/get-client-info.dto.js.map +1 -1
- package/dist/dto/get-device-token-response.dto.d.ts +21 -0
- package/dist/dto/get-device-token-response.dto.d.ts.map +1 -1
- package/dist/dto/get-device-token-response.dto.js +21 -0
- package/dist/dto/get-device-token-response.dto.js.map +1 -1
- package/dist/dto/get-events-by-type.dto.d.ts +50 -0
- package/dist/dto/get-events-by-type.dto.d.ts.map +1 -1
- package/dist/dto/get-events-by-type.dto.js +50 -0
- package/dist/dto/get-events-by-type.dto.js.map +1 -1
- package/dist/dto/get-ip-address-response.dto.d.ts +20 -0
- package/dist/dto/get-ip-address-response.dto.d.ts.map +1 -1
- package/dist/dto/get-ip-address-response.dto.js +20 -0
- package/dist/dto/get-ip-address-response.dto.js.map +1 -1
- package/dist/dto/get-mfa-status.dto.d.ts +59 -0
- package/dist/dto/get-mfa-status.dto.d.ts.map +1 -1
- package/dist/dto/get-mfa-status.dto.js +59 -0
- package/dist/dto/get-mfa-status.dto.js.map +1 -1
- package/dist/dto/get-risk-assessment-history.dto.d.ts +28 -0
- package/dist/dto/get-risk-assessment-history.dto.d.ts.map +1 -1
- package/dist/dto/get-risk-assessment-history.dto.js +28 -0
- package/dist/dto/get-risk-assessment-history.dto.js.map +1 -1
- package/dist/dto/get-session-id-response.dto.d.ts +21 -0
- package/dist/dto/get-session-id-response.dto.d.ts.map +1 -1
- package/dist/dto/get-session-id-response.dto.js +21 -0
- package/dist/dto/get-session-id-response.dto.js.map +1 -1
- package/dist/dto/get-setup-data-response.dto.d.ts +27 -0
- package/dist/dto/get-setup-data-response.dto.d.ts.map +1 -1
- package/dist/dto/get-setup-data-response.dto.js +27 -0
- package/dist/dto/get-setup-data-response.dto.js.map +1 -1
- package/dist/dto/get-setup-data.dto.d.ts +51 -0
- package/dist/dto/get-setup-data.dto.d.ts.map +1 -1
- package/dist/dto/get-setup-data.dto.js +51 -0
- package/dist/dto/get-setup-data.dto.js.map +1 -1
- package/dist/dto/get-suspicious-activity.dto.d.ts +31 -0
- package/dist/dto/get-suspicious-activity.dto.d.ts.map +1 -1
- package/dist/dto/get-suspicious-activity.dto.js +31 -0
- package/dist/dto/get-suspicious-activity.dto.js.map +1 -1
- package/dist/dto/get-user-agent-response.dto.d.ts +19 -0
- package/dist/dto/get-user-agent-response.dto.d.ts.map +1 -1
- package/dist/dto/get-user-agent-response.dto.js +19 -0
- package/dist/dto/get-user-agent-response.dto.js.map +1 -1
- package/dist/dto/get-user-auth-history.dto.d.ts +64 -0
- package/dist/dto/get-user-auth-history.dto.d.ts.map +1 -1
- package/dist/dto/get-user-auth-history.dto.js +64 -0
- package/dist/dto/get-user-auth-history.dto.js.map +1 -1
- package/dist/dto/get-user-by-email.dto.d.ts +42 -0
- package/dist/dto/get-user-by-email.dto.d.ts.map +1 -1
- package/dist/dto/get-user-by-email.dto.js +42 -0
- package/dist/dto/get-user-by-email.dto.js.map +1 -1
- package/dist/dto/get-user-by-id.dto.d.ts +32 -0
- package/dist/dto/get-user-by-id.dto.d.ts.map +1 -1
- package/dist/dto/get-user-by-id.dto.js +32 -0
- package/dist/dto/get-user-by-id.dto.js.map +1 -1
- package/dist/dto/get-user-devices.dto.d.ts +34 -0
- package/dist/dto/get-user-devices.dto.d.ts.map +1 -1
- package/dist/dto/get-user-devices.dto.js +34 -0
- package/dist/dto/get-user-devices.dto.js.map +1 -1
- package/dist/dto/get-user-response.dto.d.ts +14 -0
- package/dist/dto/get-user-response.dto.d.ts.map +1 -1
- package/dist/dto/get-user-response.dto.js +15 -0
- package/dist/dto/get-user-response.dto.js.map +1 -1
- package/dist/dto/has-provider.dto.d.ts +33 -0
- package/dist/dto/has-provider.dto.d.ts.map +1 -1
- package/dist/dto/has-provider.dto.js +33 -0
- package/dist/dto/has-provider.dto.js.map +1 -1
- package/dist/dto/index.js +5 -0
- package/dist/dto/index.js.map +1 -1
- package/dist/dto/is-trusted-device-response.dto.d.ts +28 -0
- package/dist/dto/is-trusted-device-response.dto.d.ts.map +1 -1
- package/dist/dto/is-trusted-device-response.dto.js +28 -0
- package/dist/dto/is-trusted-device-response.dto.js.map +1 -1
- package/dist/dto/list-providers-response.dto.d.ts +19 -0
- package/dist/dto/list-providers-response.dto.d.ts.map +1 -1
- package/dist/dto/list-providers-response.dto.js +19 -0
- package/dist/dto/list-providers-response.dto.js.map +1 -1
- package/dist/dto/login.dto.d.ts +48 -0
- package/dist/dto/login.dto.d.ts.map +1 -1
- package/dist/dto/login.dto.js +50 -1
- package/dist/dto/login.dto.js.map +1 -1
- package/dist/dto/logout-all-response.dto.d.ts +20 -0
- package/dist/dto/logout-all-response.dto.d.ts.map +1 -1
- package/dist/dto/logout-all-response.dto.js +20 -0
- package/dist/dto/logout-all-response.dto.js.map +1 -1
- package/dist/dto/logout-all.dto.d.ts +42 -0
- package/dist/dto/logout-all.dto.d.ts.map +1 -1
- package/dist/dto/logout-all.dto.js +42 -0
- package/dist/dto/logout-all.dto.js.map +1 -1
- package/dist/dto/logout-response.dto.d.ts +21 -0
- package/dist/dto/logout-response.dto.d.ts.map +1 -1
- package/dist/dto/logout-response.dto.js +21 -0
- package/dist/dto/logout-response.dto.js.map +1 -1
- package/dist/dto/logout.dto.d.ts +45 -0
- package/dist/dto/logout.dto.d.ts.map +1 -1
- package/dist/dto/logout.dto.js +45 -0
- package/dist/dto/logout.dto.js.map +1 -1
- package/dist/dto/refresh-token.dto.d.ts +28 -0
- package/dist/dto/refresh-token.dto.d.ts.map +1 -1
- package/dist/dto/refresh-token.dto.js +28 -0
- package/dist/dto/refresh-token.dto.js.map +1 -1
- package/dist/dto/remove-devices.dto.d.ts +51 -0
- package/dist/dto/remove-devices.dto.d.ts.map +1 -1
- package/dist/dto/remove-devices.dto.js +51 -0
- package/dist/dto/remove-devices.dto.js.map +1 -1
- package/dist/dto/resend-code-response.dto.d.ts +28 -0
- package/dist/dto/resend-code-response.dto.d.ts.map +1 -1
- package/dist/dto/resend-code-response.dto.js +28 -0
- package/dist/dto/resend-code-response.dto.js.map +1 -1
- package/dist/dto/resend-code.dto.d.ts +37 -0
- package/dist/dto/resend-code.dto.d.ts.map +1 -1
- package/dist/dto/resend-code.dto.js +37 -0
- package/dist/dto/resend-code.dto.js.map +1 -1
- package/dist/dto/reset-password.dto.d.ts +74 -0
- package/dist/dto/reset-password.dto.d.ts.map +1 -1
- package/dist/dto/reset-password.dto.js +76 -1
- package/dist/dto/reset-password.dto.js.map +1 -1
- package/dist/dto/respond-challenge.dto.d.ts +147 -0
- package/dist/dto/respond-challenge.dto.d.ts.map +1 -1
- package/dist/dto/respond-challenge.dto.js +162 -0
- package/dist/dto/respond-challenge.dto.js.map +1 -1
- package/dist/dto/set-mfa-exemption.dto.d.ts +65 -0
- package/dist/dto/set-mfa-exemption.dto.d.ts.map +1 -1
- package/dist/dto/set-mfa-exemption.dto.js +65 -0
- package/dist/dto/set-mfa-exemption.dto.js.map +1 -1
- package/dist/dto/set-must-change-password-response.dto.d.ts +23 -0
- package/dist/dto/set-must-change-password-response.dto.d.ts.map +1 -1
- package/dist/dto/set-must-change-password-response.dto.js +23 -0
- package/dist/dto/set-must-change-password-response.dto.js.map +1 -1
- package/dist/dto/set-must-change-password.dto.d.ts +32 -0
- package/dist/dto/set-must-change-password.dto.d.ts.map +1 -1
- package/dist/dto/set-must-change-password.dto.js +32 -0
- package/dist/dto/set-must-change-password.dto.js.map +1 -1
- package/dist/dto/set-preferred-method.dto.d.ts +48 -0
- package/dist/dto/set-preferred-method.dto.d.ts.map +1 -1
- package/dist/dto/set-preferred-method.dto.js +48 -0
- package/dist/dto/set-preferred-method.dto.js.map +1 -1
- package/dist/dto/setup-mfa.dto.d.ts +62 -0
- package/dist/dto/setup-mfa.dto.d.ts.map +1 -1
- package/dist/dto/setup-mfa.dto.js +62 -0
- package/dist/dto/setup-mfa.dto.js.map +1 -1
- package/dist/dto/signup.dto.d.ts +92 -0
- package/dist/dto/signup.dto.d.ts.map +1 -1
- package/dist/dto/signup.dto.js +93 -0
- package/dist/dto/signup.dto.js.map +1 -1
- package/dist/dto/social-auth.dto.d.ts +234 -0
- package/dist/dto/social-auth.dto.d.ts.map +1 -1
- package/dist/dto/social-auth.dto.js +234 -0
- package/dist/dto/social-auth.dto.js.map +1 -1
- package/dist/dto/trust-device-response.dto.d.ts +26 -0
- package/dist/dto/trust-device-response.dto.d.ts.map +1 -1
- package/dist/dto/trust-device-response.dto.js +26 -0
- package/dist/dto/trust-device-response.dto.js.map +1 -1
- package/dist/dto/trust-device.dto.d.ts +9 -0
- package/dist/dto/trust-device.dto.d.ts.map +1 -1
- package/dist/dto/trust-device.dto.js +9 -0
- package/dist/dto/trust-device.dto.js.map +1 -1
- package/dist/dto/update-user-attributes-request.dto.d.ts +36 -0
- package/dist/dto/update-user-attributes-request.dto.d.ts.map +1 -1
- package/dist/dto/update-user-attributes-request.dto.js +36 -0
- package/dist/dto/update-user-attributes-request.dto.js.map +1 -1
- package/dist/dto/user-response.dto.d.ts +81 -0
- package/dist/dto/user-response.dto.d.ts.map +1 -1
- package/dist/dto/user-response.dto.js +84 -2
- package/dist/dto/user-response.dto.js.map +1 -1
- package/dist/dto/user-update.dto.d.ts +132 -0
- package/dist/dto/user-update.dto.d.ts.map +1 -1
- package/dist/dto/user-update.dto.js +133 -0
- package/dist/dto/user-update.dto.js.map +1 -1
- package/dist/dto/verify-email.dto.d.ts +171 -0
- package/dist/dto/verify-email.dto.d.ts.map +1 -1
- package/dist/dto/verify-email.dto.js +173 -1
- package/dist/dto/verify-email.dto.js.map +1 -1
- package/dist/dto/verify-mfa-code.dto.d.ts +65 -0
- package/dist/dto/verify-mfa-code.dto.d.ts.map +1 -1
- package/dist/dto/verify-mfa-code.dto.js +65 -0
- package/dist/dto/verify-mfa-code.dto.js.map +1 -1
- package/dist/dto/verify-phone-by-sub.dto.d.ts +49 -0
- package/dist/dto/verify-phone-by-sub.dto.d.ts.map +1 -1
- package/dist/dto/verify-phone-by-sub.dto.js +49 -0
- package/dist/dto/verify-phone-by-sub.dto.js.map +1 -1
- package/dist/dto/verify-phone.dto.d.ts +139 -0
- package/dist/dto/verify-phone.dto.d.ts.map +1 -1
- package/dist/dto/verify-phone.dto.js +142 -1
- package/dist/dto/verify-phone.dto.js.map +1 -1
- package/dist/dto.d.ts +10 -0
- package/dist/dto.d.ts.map +1 -1
- package/dist/dto.js +10 -0
- package/dist/dto.js.map +1 -1
- package/dist/entities/auth-audit.entity.d.ts +159 -0
- package/dist/entities/auth-audit.entity.d.ts.map +1 -1
- package/dist/entities/auth-audit.entity.js +166 -0
- package/dist/entities/auth-audit.entity.js.map +1 -1
- package/dist/entities/challenge-session.entity.d.ts +87 -0
- package/dist/entities/challenge-session.entity.d.ts.map +1 -1
- package/dist/entities/challenge-session.entity.js +87 -0
- package/dist/entities/challenge-session.entity.js.map +1 -1
- package/dist/entities/index.d.ts +18 -0
- package/dist/entities/index.d.ts.map +1 -1
- package/dist/entities/index.js +18 -0
- package/dist/entities/index.js.map +1 -1
- package/dist/entities/login-attempt.entity.d.ts +43 -0
- package/dist/entities/login-attempt.entity.d.ts.map +1 -1
- package/dist/entities/login-attempt.entity.js +43 -0
- package/dist/entities/login-attempt.entity.js.map +1 -1
- package/dist/entities/mfa-device.entity.d.ts +112 -0
- package/dist/entities/mfa-device.entity.d.ts.map +1 -1
- package/dist/entities/mfa-device.entity.js +112 -0
- package/dist/entities/mfa-device.entity.js.map +1 -1
- package/dist/entities/rate-limit.entity.d.ts +31 -0
- package/dist/entities/rate-limit.entity.d.ts.map +1 -1
- package/dist/entities/rate-limit.entity.js +31 -0
- package/dist/entities/rate-limit.entity.js.map +1 -1
- package/dist/entities/session.entity.d.ts +121 -0
- package/dist/entities/session.entity.d.ts.map +1 -1
- package/dist/entities/session.entity.js +121 -0
- package/dist/entities/session.entity.js.map +1 -1
- package/dist/entities/social-account.entity.d.ts +75 -0
- package/dist/entities/social-account.entity.d.ts.map +1 -1
- package/dist/entities/social-account.entity.js +75 -0
- package/dist/entities/social-account.entity.js.map +1 -1
- package/dist/entities/storage-lock.entity.d.ts +28 -0
- package/dist/entities/storage-lock.entity.d.ts.map +1 -1
- package/dist/entities/storage-lock.entity.js +28 -0
- package/dist/entities/storage-lock.entity.js.map +1 -1
- package/dist/entities/trusted-device.entity.d.ts +83 -0
- package/dist/entities/trusted-device.entity.d.ts.map +1 -1
- package/dist/entities/trusted-device.entity.js +83 -0
- package/dist/entities/trusted-device.entity.js.map +1 -1
- package/dist/entities/user.entity.d.ts +166 -0
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +166 -0
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/verification-token.entity.d.ts +102 -0
- package/dist/entities/verification-token.entity.d.ts.map +1 -1
- package/dist/entities/verification-token.entity.js +102 -0
- package/dist/entities/verification-token.entity.js.map +1 -1
- package/dist/entities.d.ts +8 -0
- package/dist/entities.d.ts.map +1 -1
- package/dist/entities.js +8 -0
- package/dist/entities.js.map +1 -1
- package/dist/enums/auth-audit-event-type.enum.d.ts +211 -0
- package/dist/enums/auth-audit-event-type.enum.d.ts.map +1 -1
- package/dist/enums/auth-audit-event-type.enum.js +244 -0
- package/dist/enums/auth-audit-event-type.enum.js.map +1 -1
- package/dist/enums/error-codes.enum.d.ts +296 -0
- package/dist/enums/error-codes.enum.d.ts.map +1 -1
- package/dist/enums/error-codes.enum.js +332 -0
- package/dist/enums/error-codes.enum.js.map +1 -1
- package/dist/enums/mfa-method.enum.d.ts +74 -0
- package/dist/enums/mfa-method.enum.d.ts.map +1 -1
- package/dist/enums/mfa-method.enum.js +64 -0
- package/dist/enums/mfa-method.enum.js.map +1 -1
- package/dist/enums/risk-factor.enum.d.ts +91 -0
- package/dist/enums/risk-factor.enum.d.ts.map +1 -1
- package/dist/enums/risk-factor.enum.js +97 -0
- package/dist/enums/risk-factor.enum.js.map +1 -1
- package/dist/exceptions/nauth.exception.d.ts +149 -0
- package/dist/exceptions/nauth.exception.d.ts.map +1 -1
- package/dist/exceptions/nauth.exception.js +159 -0
- package/dist/exceptions/nauth.exception.js.map +1 -1
- package/dist/handlers/auth.handler.d.ts +32 -0
- package/dist/handlers/auth.handler.d.ts.map +1 -1
- package/dist/handlers/auth.handler.js +47 -1
- package/dist/handlers/auth.handler.js.map +1 -1
- package/dist/handlers/client-info.handler.d.ts +25 -0
- package/dist/handlers/client-info.handler.d.ts.map +1 -1
- package/dist/handlers/client-info.handler.js +36 -2
- package/dist/handlers/client-info.handler.js.map +1 -1
- package/dist/handlers/csrf.handler.d.ts +32 -0
- package/dist/handlers/csrf.handler.d.ts.map +1 -1
- package/dist/handlers/csrf.handler.js +49 -1
- package/dist/handlers/csrf.handler.js.map +1 -1
- package/dist/handlers/token-delivery.handler.d.ts +16 -0
- package/dist/handlers/token-delivery.handler.d.ts.map +1 -1
- package/dist/handlers/token-delivery.handler.js +22 -1
- package/dist/handlers/token-delivery.handler.js.map +1 -1
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/client-info.interface.d.ts +58 -0
- package/dist/interfaces/client-info.interface.d.ts.map +1 -1
- package/dist/interfaces/config.interface.d.ts +1774 -0
- package/dist/interfaces/config.interface.d.ts.map +1 -1
- package/dist/interfaces/config.interface.js +16 -0
- package/dist/interfaces/config.interface.js.map +1 -1
- package/dist/interfaces/entities.interface.d.ts +48 -0
- package/dist/interfaces/entities.interface.d.ts.map +1 -1
- package/dist/interfaces/entities.interface.js +8 -0
- package/dist/interfaces/entities.interface.js.map +1 -1
- package/dist/interfaces/index.js +5 -0
- package/dist/interfaces/index.js.map +1 -1
- package/dist/interfaces/logger.interface.d.ts +213 -0
- package/dist/interfaces/logger.interface.d.ts.map +1 -1
- package/dist/interfaces/logger.interface.js +35 -0
- package/dist/interfaces/logger.interface.js.map +1 -1
- package/dist/interfaces/mfa-provider.interface.d.ts +134 -0
- package/dist/interfaces/mfa-provider.interface.d.ts.map +1 -1
- package/dist/interfaces/oauth.interface.d.ts +110 -0
- package/dist/interfaces/oauth.interface.d.ts.map +1 -1
- package/dist/interfaces/provider.interface.d.ts +83 -0
- package/dist/interfaces/provider.interface.d.ts.map +1 -1
- package/dist/interfaces/sms-template.interface.d.ts +246 -0
- package/dist/interfaces/sms-template.interface.d.ts.map +1 -1
- package/dist/interfaces/sms-template.interface.js +26 -0
- package/dist/interfaces/sms-template.interface.js.map +1 -1
- package/dist/interfaces/social-auth-provider.interface.d.ts +115 -0
- package/dist/interfaces/social-auth-provider.interface.d.ts.map +1 -1
- package/dist/interfaces/storage-adapter.interface.d.ts +37 -0
- package/dist/interfaces/storage-adapter.interface.d.ts.map +1 -1
- package/dist/interfaces/template.interface.d.ts +351 -0
- package/dist/interfaces/template.interface.d.ts.map +1 -1
- package/dist/interfaces/template.interface.js +13 -0
- package/dist/interfaces/template.interface.js.map +1 -1
- package/dist/interfaces/token-verifier.interface.d.ts +101 -0
- package/dist/interfaces/token-verifier.interface.d.ts.map +1 -1
- package/dist/interfaces.d.ts +8 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +8 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/internal.d.ts +120 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +138 -0
- package/dist/internal.js.map +1 -1
- package/dist/platform/interfaces.d.ts +187 -0
- package/dist/platform/interfaces.d.ts.map +1 -1
- package/dist/platform/interfaces.js +11 -0
- package/dist/platform/interfaces.js.map +1 -1
- package/dist/schemas/auth-config.schema.d.ts +48 -0
- package/dist/schemas/auth-config.schema.d.ts.map +1 -1
- package/dist/schemas/auth-config.schema.js +188 -9
- package/dist/schemas/auth-config.schema.js.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.d.ts +144 -0
- package/dist/services/adaptive-mfa-decision.service.d.ts.map +1 -1
- package/dist/services/adaptive-mfa-decision.service.js +151 -5
- package/dist/services/adaptive-mfa-decision.service.js.map +1 -1
- package/dist/services/auth-audit.service.d.ts +195 -0
- package/dist/services/auth-audit.service.d.ts.map +1 -1
- package/dist/services/auth-audit.service.js +228 -1
- package/dist/services/auth-audit.service.js.map +1 -1
- package/dist/services/auth-challenge-helper.service.d.ts +144 -1
- package/dist/services/auth-challenge-helper.service.d.ts.map +1 -1
- package/dist/services/auth-challenge-helper.service.js +295 -16
- package/dist/services/auth-challenge-helper.service.js.map +1 -1
- package/dist/services/auth-flow-context-builder.service.d.ts +120 -1
- package/dist/services/auth-flow-context-builder.service.d.ts.map +1 -1
- package/dist/services/auth-flow-context-builder.service.js +184 -5
- package/dist/services/auth-flow-context-builder.service.js.map +1 -1
- package/dist/services/auth-flow-rules.d.ts +136 -0
- package/dist/services/auth-flow-rules.d.ts.map +1 -1
- package/dist/services/auth-flow-rules.js +137 -0
- package/dist/services/auth-flow-rules.js.map +1 -1
- package/dist/services/auth-flow-state-definitions.d.ts +40 -0
- package/dist/services/auth-flow-state-definitions.d.ts.map +1 -1
- package/dist/services/auth-flow-state-definitions.js +98 -0
- package/dist/services/auth-flow-state-definitions.js.map +1 -1
- package/dist/services/auth-flow-state-machine.service.d.ts +91 -0
- package/dist/services/auth-flow-state-machine.service.d.ts.map +1 -1
- package/dist/services/auth-flow-state-machine.service.js +102 -0
- package/dist/services/auth-flow-state-machine.service.js.map +1 -1
- package/dist/services/auth-flow-state-machine.types.d.ts +221 -0
- package/dist/services/auth-flow-state-machine.types.d.ts.map +1 -1
- package/dist/services/auth-flow-state-machine.types.js +47 -0
- package/dist/services/auth-flow-state-machine.types.js.map +1 -1
- package/dist/services/auth.service.d.ts +397 -1
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js +943 -27
- package/dist/services/auth.service.js.map +1 -1
- package/dist/services/challenge.service.d.ts +255 -1
- package/dist/services/challenge.service.d.ts.map +1 -1
- package/dist/services/challenge.service.js +327 -3
- package/dist/services/challenge.service.js.map +1 -1
- package/dist/services/client-info.service.d.ts +143 -0
- package/dist/services/client-info.service.d.ts.map +1 -1
- package/dist/services/client-info.service.js +161 -0
- package/dist/services/client-info.service.js.map +1 -1
- package/dist/services/csrf.service.d.ts +15 -0
- package/dist/services/csrf.service.d.ts.map +1 -1
- package/dist/services/csrf.service.js +16 -0
- package/dist/services/csrf.service.js.map +1 -1
- package/dist/services/email-verification.service.d.ts +52 -0
- package/dist/services/email-verification.service.d.ts.map +1 -1
- package/dist/services/email-verification.service.js +149 -10
- package/dist/services/email-verification.service.js.map +1 -1
- package/dist/services/geo-location.service.d.ts +105 -0
- package/dist/services/geo-location.service.d.ts.map +1 -1
- package/dist/services/geo-location.service.js +188 -2
- package/dist/services/geo-location.service.js.map +1 -1
- package/dist/services/jwt.service.d.ts +257 -0
- package/dist/services/jwt.service.d.ts.map +1 -1
- package/dist/services/jwt.service.js +284 -1
- package/dist/services/jwt.service.js.map +1 -1
- package/dist/services/mfa-base.service.d.ts +179 -1
- package/dist/services/mfa-base.service.d.ts.map +1 -1
- package/dist/services/mfa-base.service.js +256 -2
- package/dist/services/mfa-base.service.js.map +1 -1
- package/dist/services/mfa.service.d.ts +304 -0
- package/dist/services/mfa.service.d.ts.map +1 -1
- package/dist/services/mfa.service.js +380 -0
- package/dist/services/mfa.service.js.map +1 -1
- package/dist/services/password-reset.service.d.ts +46 -0
- package/dist/services/password-reset.service.d.ts.map +1 -1
- package/dist/services/password-reset.service.js +79 -0
- package/dist/services/password-reset.service.js.map +1 -1
- package/dist/services/password.service.d.ts +139 -0
- package/dist/services/password.service.d.ts.map +1 -1
- package/dist/services/password.service.js +167 -9
- package/dist/services/password.service.js.map +1 -1
- package/dist/services/phone-verification.service.d.ts +75 -0
- package/dist/services/phone-verification.service.d.ts.map +1 -1
- package/dist/services/phone-verification.service.js +188 -6
- package/dist/services/phone-verification.service.js.map +1 -1
- package/dist/services/risk-detection.service.d.ts +198 -0
- package/dist/services/risk-detection.service.d.ts.map +1 -1
- package/dist/services/risk-detection.service.js +358 -11
- package/dist/services/risk-detection.service.js.map +1 -1
- package/dist/services/risk-scoring.service.d.ts +84 -0
- package/dist/services/risk-scoring.service.d.ts.map +1 -1
- package/dist/services/risk-scoring.service.js +87 -0
- package/dist/services/risk-scoring.service.js.map +1 -1
- package/dist/services/session.service.d.ts +204 -0
- package/dist/services/session.service.d.ts.map +1 -1
- package/dist/services/session.service.js +289 -4
- package/dist/services/session.service.js.map +1 -1
- package/dist/services/social-auth-base.service.d.ts +123 -1
- package/dist/services/social-auth-base.service.d.ts.map +1 -1
- package/dist/services/social-auth-base.service.js +155 -2
- package/dist/services/social-auth-base.service.js.map +1 -1
- package/dist/services/social-auth.service.d.ts +191 -0
- package/dist/services/social-auth.service.d.ts.map +1 -1
- package/dist/services/social-auth.service.js +215 -2
- package/dist/services/social-auth.service.js.map +1 -1
- package/dist/services/social-provider-registry.service.d.ts +86 -0
- package/dist/services/social-provider-registry.service.d.ts.map +1 -1
- package/dist/services/social-provider-registry.service.js +86 -0
- package/dist/services/social-provider-registry.service.js.map +1 -1
- package/dist/services/trusted-device.service.d.ts +105 -0
- package/dist/services/trusted-device.service.d.ts.map +1 -1
- package/dist/services/trusted-device.service.js +133 -4
- package/dist/services/trusted-device.service.js.map +1 -1
- package/dist/storage/account-lockout-storage.service.d.ts +35 -0
- package/dist/storage/account-lockout-storage.service.d.ts.map +1 -1
- package/dist/storage/account-lockout-storage.service.js +35 -0
- package/dist/storage/account-lockout-storage.service.js.map +1 -1
- package/dist/storage/memory-storage.adapter.d.ts +148 -0
- package/dist/storage/memory-storage.adapter.d.ts.map +1 -1
- package/dist/storage/memory-storage.adapter.js +201 -6
- package/dist/storage/memory-storage.adapter.js.map +1 -1
- package/dist/storage/rate-limit-storage.service.d.ts +3 -0
- package/dist/storage/rate-limit-storage.service.d.ts.map +1 -1
- package/dist/storage/rate-limit-storage.service.js +4 -0
- package/dist/storage/rate-limit-storage.service.js.map +1 -1
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +8 -0
- package/dist/storage.js.map +1 -1
- package/dist/templates/html-template.engine.d.ts +110 -0
- package/dist/templates/html-template.engine.d.ts.map +1 -1
- package/dist/templates/html-template.engine.js +147 -0
- package/dist/templates/html-template.engine.js.map +1 -1
- package/dist/templates/index.d.ts +5 -0
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +5 -0
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/sms-template.engine.d.ts +151 -0
- package/dist/templates/sms-template.engine.d.ts.map +1 -1
- package/dist/templates/sms-template.engine.js +171 -0
- package/dist/templates/sms-template.engine.js.map +1 -1
- package/dist/templates.d.ts +8 -0
- package/dist/templates.d.ts.map +1 -1
- package/dist/templates.js +8 -0
- package/dist/templates.js.map +1 -1
- package/dist/utils/common-passwords.d.ts +42 -0
- package/dist/utils/common-passwords.d.ts.map +1 -1
- package/dist/utils/common-passwords.js +88 -0
- package/dist/utils/common-passwords.js.map +1 -1
- package/dist/utils/context-storage.d.ts +129 -0
- package/dist/utils/context-storage.d.ts.map +1 -1
- package/dist/utils/context-storage.js +129 -0
- package/dist/utils/context-storage.js.map +1 -1
- package/dist/utils/cookie-names.util.d.ts +35 -0
- package/dist/utils/cookie-names.util.d.ts.map +1 -1
- package/dist/utils/cookie-names.util.js +37 -0
- package/dist/utils/cookie-names.util.js.map +1 -1
- package/dist/utils/cookies.util.d.ts +19 -0
- package/dist/utils/cookies.util.d.ts.map +1 -1
- package/dist/utils/cookies.util.js +30 -3
- package/dist/utils/cookies.util.js.map +1 -1
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/ip-extractor.d.ts +88 -0
- package/dist/utils/ip-extractor.d.ts.map +1 -1
- package/dist/utils/ip-extractor.js +109 -16
- package/dist/utils/ip-extractor.js.map +1 -1
- package/dist/utils/nauth-logger.d.ts +70 -0
- package/dist/utils/nauth-logger.d.ts.map +1 -1
- package/dist/utils/nauth-logger.js +82 -4
- package/dist/utils/nauth-logger.js.map +1 -1
- package/dist/utils/pii-redactor.d.ts +70 -0
- package/dist/utils/pii-redactor.d.ts.map +1 -1
- package/dist/utils/pii-redactor.js +102 -0
- package/dist/utils/pii-redactor.js.map +1 -1
- package/dist/utils/setup/get-repositories.d.ts +16 -0
- package/dist/utils/setup/get-repositories.d.ts.map +1 -1
- package/dist/utils/setup/get-repositories.js +21 -0
- package/dist/utils/setup/get-repositories.js.map +1 -1
- package/dist/utils/setup/init-services.d.ts +40 -1
- package/dist/utils/setup/init-services.d.ts.map +1 -1
- package/dist/utils/setup/init-services.js +98 -0
- package/dist/utils/setup/init-services.js.map +1 -1
- package/dist/utils/setup/init-social.d.ts +27 -0
- package/dist/utils/setup/init-social.d.ts.map +1 -1
- package/dist/utils/setup/init-social.js +49 -0
- package/dist/utils/setup/init-social.js.map +1 -1
- package/dist/utils/setup/init-storage.d.ts +22 -0
- package/dist/utils/setup/init-storage.d.ts.map +1 -1
- package/dist/utils/setup/init-storage.js +36 -0
- package/dist/utils/setup/init-storage.js.map +1 -1
- package/dist/utils/setup/register-mfa.d.ts +22 -0
- package/dist/utils/setup/register-mfa.d.ts.map +1 -1
- package/dist/utils/setup/register-mfa.js +41 -0
- package/dist/utils/setup/register-mfa.js.map +1 -1
- package/dist/utils/setup/run-nauth-migrations.d.ts +7 -0
- package/dist/utils/setup/run-nauth-migrations.d.ts.map +1 -1
- package/dist/utils/setup/run-nauth-migrations.js +8 -0
- package/dist/utils/setup/run-nauth-migrations.js.map +1 -1
- package/dist/utils/token-delivery-policy.d.ts +17 -0
- package/dist/utils/token-delivery-policy.d.ts.map +1 -1
- package/dist/utils/token-delivery-policy.js +17 -0
- package/dist/utils/token-delivery-policy.js.map +1 -1
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +8 -0
- package/dist/utils.js.map +1 -1
- package/dist/validators/template.validator.d.ts +80 -0
- package/dist/validators/template.validator.d.ts.map +1 -1
- package/dist/validators/template.validator.js +94 -0
- package/dist/validators/template.validator.js.map +1 -1
- package/package.json +7 -2
|
@@ -1,40 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration interface for nauth-toolkit
|
|
3
|
+
*
|
|
4
|
+
* NOTE: This interface is validated at runtime using Zod.
|
|
5
|
+
* See packages/core/src/schemas/auth-config.schema.ts for validation rules.
|
|
6
|
+
*
|
|
7
|
+
* The Zod schema validates:
|
|
8
|
+
* - Required fields and types
|
|
9
|
+
* - Cross-dependencies (e.g., email config requires emailProvider)
|
|
10
|
+
* - Algorithm-specific requirements (JWT symmetric vs asymmetric)
|
|
11
|
+
* - MFA enforcement modes and their requirements
|
|
12
|
+
* - Social provider requirements
|
|
13
|
+
* - GeoLocation MaxMind credentials
|
|
14
|
+
*
|
|
15
|
+
* Validation errors are caught at module initialization with clear, actionable messages.
|
|
16
|
+
*/
|
|
1
17
|
import { MFADeviceMethod } from '../enums/mfa-method.enum';
|
|
2
18
|
import { StorageAdapter } from './storage-adapter.interface';
|
|
3
19
|
import { EmailProvider, SMSProvider } from './provider.interface';
|
|
4
20
|
export interface NAuthConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Database table prefix
|
|
23
|
+
*
|
|
24
|
+
* @default 'nauth_'
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* tablePrefix: 'myapp_', // Tables: myapp_users, myapp_sessions, etc.
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
5
31
|
tablePrefix?: string;
|
|
32
|
+
/**
|
|
33
|
+
* JWT configuration
|
|
34
|
+
*/
|
|
6
35
|
jwt: JwtConfig;
|
|
36
|
+
/**
|
|
37
|
+
* Signup configuration
|
|
38
|
+
*/
|
|
7
39
|
signup?: SignupConfig;
|
|
40
|
+
/**
|
|
41
|
+
* Login configuration
|
|
42
|
+
*/
|
|
8
43
|
login?: LoginConfig;
|
|
44
|
+
/**
|
|
45
|
+
* Password policy configuration
|
|
46
|
+
*/
|
|
9
47
|
password?: PasswordConfig;
|
|
48
|
+
/**
|
|
49
|
+
* Account lockout configuration
|
|
50
|
+
*/
|
|
10
51
|
lockout?: LockoutConfig;
|
|
52
|
+
/**
|
|
53
|
+
* Session configuration
|
|
54
|
+
*/
|
|
11
55
|
session?: SessionConfig;
|
|
56
|
+
/**
|
|
57
|
+
* Security configuration
|
|
58
|
+
*/
|
|
12
59
|
security?: SecurityConfig;
|
|
60
|
+
/**
|
|
61
|
+
* Lifecycle hooks
|
|
62
|
+
*/
|
|
13
63
|
hooks?: LifecycleHooks;
|
|
64
|
+
/**
|
|
65
|
+
* Audit logging configuration
|
|
66
|
+
*
|
|
67
|
+
* Controls whether authentication and security events are logged to the audit trail.
|
|
68
|
+
* When disabled, audit logs are not recorded, reducing storage costs and minor performance overhead.
|
|
69
|
+
*
|
|
70
|
+
* WARNING: Highly recommended for production systems. Disabling audit logs reduces security observability.
|
|
71
|
+
*
|
|
72
|
+
* @default { enabled: true }
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // Enable audit logs (default - recommended for production)
|
|
77
|
+
* auditLogs: {
|
|
78
|
+
* enabled: true
|
|
79
|
+
* }
|
|
80
|
+
*
|
|
81
|
+
* // Disable audit logs (minimal overhead use cases only)
|
|
82
|
+
* auditLogs: {
|
|
83
|
+
* enabled: false
|
|
84
|
+
* }
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
14
87
|
auditLogs?: {
|
|
88
|
+
/**
|
|
89
|
+
* Enable audit logging
|
|
90
|
+
* @default true
|
|
91
|
+
*/
|
|
15
92
|
enabled?: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Fire-and-forget audit mode for hot paths
|
|
95
|
+
* When true, audit writes won't be awaited on request path
|
|
96
|
+
*/
|
|
16
97
|
fireAndForget?: boolean;
|
|
17
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* Email provider for sending verification emails, password resets, etc.
|
|
101
|
+
*
|
|
102
|
+
* Configure based on your needs - consumer apps choose their own env var names.
|
|
103
|
+
* All values should be passed explicitly through config, not auto-loaded.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* // Console provider (development - logs to console)
|
|
108
|
+
* import { ConsoleEmailProvider } from '@nauth-toolkit/email-console';
|
|
109
|
+
* emailProvider: new ConsoleEmailProvider()
|
|
110
|
+
*
|
|
111
|
+
* // Nodemailer with SMTP (production)
|
|
112
|
+
* import { NodemailerEmailProvider } from '@nauth-toolkit/email-nodemailer';
|
|
113
|
+
* emailProvider: new NodemailerEmailProvider({
|
|
114
|
+
* transport: {
|
|
115
|
+
* host: process.env.SMTP_HOST, // Your env var name
|
|
116
|
+
* port: parseInt(process.env.SMTP_PORT || '587'),
|
|
117
|
+
* secure: process.env.SMTP_SECURE === 'true',
|
|
118
|
+
* auth: {
|
|
119
|
+
* user: process.env.SMTP_USER,
|
|
120
|
+
* pass: process.env.SMTP_PASS,
|
|
121
|
+
* },
|
|
122
|
+
* },
|
|
123
|
+
* defaults: {
|
|
124
|
+
* from: process.env.EMAIL_FROM, // e.g., "My App <noreply@example.com>"
|
|
125
|
+
* },
|
|
126
|
+
* })
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
18
129
|
emailProvider?: EmailProvider;
|
|
130
|
+
/**
|
|
131
|
+
* Email verification configuration
|
|
132
|
+
*/
|
|
19
133
|
email?: EmailConfig;
|
|
134
|
+
/**
|
|
135
|
+
* Optional: SMS provider for sending phone verification codes
|
|
136
|
+
* If not provided, uses ConsoleSMSProvider (logs to console)
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // Use console provider (development)
|
|
141
|
+
* smsProvider: new ConsoleSMSProvider()
|
|
142
|
+
*
|
|
143
|
+
* // Use Twilio provider (production)
|
|
144
|
+
* smsProvider: new TwilioSMSProvider({ accountSid: '...', authToken: '...', fromNumber: '...' })
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
20
147
|
smsProvider?: SMSProvider;
|
|
148
|
+
/**
|
|
149
|
+
* SMS template configuration
|
|
150
|
+
*
|
|
151
|
+
* Configure custom SMS templates and global variables for branding.
|
|
152
|
+
* Templates are validated at startup to ensure required parameters are present.
|
|
153
|
+
*
|
|
154
|
+
* Note: Top-level branding fields (appName, companyName, etc.) are automatically
|
|
155
|
+
* merged into sms.templates.globalVariables. You can override them in globalVariables if needed.
|
|
156
|
+
*
|
|
157
|
+
* @example Basic configuration with top-level branding
|
|
158
|
+
* ```typescript
|
|
159
|
+
* sms: {
|
|
160
|
+
* templates: {
|
|
161
|
+
* globalVariables: {
|
|
162
|
+
* appName: process.env.APP_NAME || 'My Application',
|
|
163
|
+
* companyName: process.env.COMPANY_NAME || 'My Company Inc.',
|
|
164
|
+
* supportPhone: process.env.SUPPORT_PHONE || '+1-800-123-4567',
|
|
165
|
+
* },
|
|
166
|
+
* },
|
|
167
|
+
* }
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @example Advanced configuration with custom templates
|
|
171
|
+
* ```typescript
|
|
172
|
+
* sms: {
|
|
173
|
+
* templates: {
|
|
174
|
+
* globalVariables: {
|
|
175
|
+
* appName: 'My App',
|
|
176
|
+
* companyName: 'My Company',
|
|
177
|
+
* },
|
|
178
|
+
* customTemplates: {
|
|
179
|
+
* verification: {
|
|
180
|
+
* content: '{{appName}}: Your verification code is {{code}}. Expires in {{expiryMinutes}} min.',
|
|
181
|
+
* // Must include: {{code}}, {{expiryMinutes}}
|
|
182
|
+
* },
|
|
183
|
+
* mfa: {
|
|
184
|
+
* contentPath: './sms-templates/mfa.txt.hbs',
|
|
185
|
+
* // Must include: {{code}}, {{expiryMinutes}}
|
|
186
|
+
* },
|
|
187
|
+
* },
|
|
188
|
+
* },
|
|
189
|
+
* }
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
21
192
|
sms?: {
|
|
22
193
|
templates?: import('./sms-template.interface').SMSTemplateConfig;
|
|
23
194
|
};
|
|
195
|
+
/**
|
|
196
|
+
* Phone verification configuration
|
|
197
|
+
*/
|
|
24
198
|
phone?: PhoneConfig;
|
|
199
|
+
/**
|
|
200
|
+
* Storage adapter for transient state (rate limits, locks, token reuse tracking)
|
|
201
|
+
*
|
|
202
|
+
* WARNING: PRODUCTION REQUIREMENT - Storage adapter is REQUIRED for production deployments.
|
|
203
|
+
*
|
|
204
|
+
* Default Behavior:
|
|
205
|
+
* - If not provided and storage entities are available: DatabaseStorageAdapter is used automatically
|
|
206
|
+
* - If not provided and storage entities are NOT available: Configuration fails with helpful error message
|
|
207
|
+
*
|
|
208
|
+
* MemoryStorageAdapter is NOT safe for production:
|
|
209
|
+
* - Data lost on server restart
|
|
210
|
+
* - NOT shared across multiple server instances
|
|
211
|
+
* - Rate limiting per-container (not global in multi-container setups)
|
|
212
|
+
* - Token reuse detection fails in multi-server deployments
|
|
213
|
+
*
|
|
214
|
+
* Recommended: DatabaseStorageAdapter (default, uses existing TypeORM connection, no additional infrastructure)
|
|
215
|
+
* Alternative: RedisStorageAdapter (for high-performance multi-server deployments)
|
|
216
|
+
* Production: RedisClusterAdapter (for high-availability production clusters)
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```typescript
|
|
220
|
+
* // Database adapter (default - uses existing TypeORM connection, no additional infrastructure)
|
|
221
|
+
* import { createDatabaseStorageAdapter } from '@nauth-toolkit/nestjs';
|
|
222
|
+
* storageAdapter: createDatabaseStorageAdapter()
|
|
223
|
+
*
|
|
224
|
+
* // Redis adapter (for high-performance multi-server deployments)
|
|
225
|
+
* import { createRedisStorageAdapter } from '@nauth-toolkit/nestjs';
|
|
226
|
+
* storageAdapter: createRedisStorageAdapter(process.env.REDIS_URL)
|
|
227
|
+
*
|
|
228
|
+
* // Redis Cluster adapter (for high-availability production deployments)
|
|
229
|
+
* import { createRedisClusterAdapter } from '@nauth-toolkit/nestjs';
|
|
230
|
+
* storageAdapter: createRedisClusterAdapter([
|
|
231
|
+
* { url: 'redis://redis-node-1:6379' },
|
|
232
|
+
* { url: 'redis://redis-node-2:6379' },
|
|
233
|
+
* { url: 'redis://redis-node-3:6379' },
|
|
234
|
+
* ])
|
|
235
|
+
*
|
|
236
|
+
* // Auto-detect (uses DatabaseStorageAdapter if entities available)
|
|
237
|
+
* storageAdapter: undefined
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
25
240
|
storageAdapter?: StorageAdapter;
|
|
241
|
+
/**
|
|
242
|
+
* Social login configuration
|
|
243
|
+
* Configure OAuth providers for social authentication
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* social: {
|
|
248
|
+
* google: {
|
|
249
|
+
* enabled: true,
|
|
250
|
+
* clientId: process.env.GOOGLE_CLIENT_ID, // Your env var name
|
|
251
|
+
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
252
|
+
* callbackUrl: 'https://myapp.com/auth/google/callback',
|
|
253
|
+
* autoLink: true,
|
|
254
|
+
* allowSignup: true
|
|
255
|
+
* },
|
|
256
|
+
* apple: {
|
|
257
|
+
* enabled: true,
|
|
258
|
+
* clientId: process.env.APPLE_CLIENT_ID, // Your env var name
|
|
259
|
+
* clientSecret: process.env.APPLE_CLIENT_SECRET,
|
|
260
|
+
* callbackUrl: 'https://myapp.com/auth/apple/callback',
|
|
261
|
+
* autoLink: true,
|
|
262
|
+
* allowSignup: true
|
|
263
|
+
* }
|
|
264
|
+
* }
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
26
267
|
social?: SocialConfig;
|
|
268
|
+
/**
|
|
269
|
+
* Multi-Factor Authentication (MFA) configuration
|
|
270
|
+
*
|
|
271
|
+
* Supports multiple MFA methods: TOTP (authenticator apps), SMS, Email, and Passkeys (WebAuthn).
|
|
272
|
+
* Users can register multiple devices for redundancy.
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* mfa: {
|
|
277
|
+
* enabled: true,
|
|
278
|
+
* enforcement: 'OPTIONAL',
|
|
279
|
+
* allowedMethods: [MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY],
|
|
280
|
+
* issuer: 'MyApp',
|
|
281
|
+
* totp: {
|
|
282
|
+
* window: 1,
|
|
283
|
+
* stepSeconds: 30
|
|
284
|
+
* },
|
|
285
|
+
* passkey: {
|
|
286
|
+
* rpName: 'MyApp',
|
|
287
|
+
* rpId: 'myapp.com',
|
|
288
|
+
* timeout: 60000
|
|
289
|
+
* },
|
|
290
|
+
* backup: {
|
|
291
|
+
* enabled: true,
|
|
292
|
+
* codeCount: 10
|
|
293
|
+
* }
|
|
294
|
+
* }
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
27
297
|
mfa?: MFAConfig;
|
|
298
|
+
/**
|
|
299
|
+
* Optional: Logger configuration for nauth-toolkit internal logging
|
|
300
|
+
* Compatible with NestJS LoggerService interface
|
|
301
|
+
* If not provided, nauth-toolkit will be silent (no logs)
|
|
302
|
+
*
|
|
303
|
+
* All logs will be prefixed with "NAUTH:" for easy identification
|
|
304
|
+
* PII redaction is enabled by default for security compliance
|
|
305
|
+
*
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* import { Logger } from '@nestjs/common';
|
|
309
|
+
*
|
|
310
|
+
* // Use NestJS built-in logger with default settings (PII redaction enabled)
|
|
311
|
+
* logger: new Logger('NAuth')
|
|
312
|
+
*
|
|
313
|
+
* // Use custom logger with options
|
|
314
|
+
* logger: {
|
|
315
|
+
* instance: new Logger('NAuth'),
|
|
316
|
+
* enablePiiRedaction: true, // Default: true
|
|
317
|
+
* logLevel: 'debug' // Optional: control log level
|
|
318
|
+
* }
|
|
319
|
+
*
|
|
320
|
+
* // Disable PII redaction (for debugging - not recommended in production)
|
|
321
|
+
* logger: {
|
|
322
|
+
* instance: myCustomLogger,
|
|
323
|
+
* enablePiiRedaction: false
|
|
324
|
+
* }
|
|
325
|
+
*
|
|
326
|
+
* // No logger = silent mode (default)
|
|
327
|
+
* logger: undefined
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
28
330
|
logger?: LoggerService | NAuthLoggerConfig;
|
|
331
|
+
/**
|
|
332
|
+
* Token delivery configuration
|
|
333
|
+
*
|
|
334
|
+
* Controls how JWT tokens are delivered to clients.
|
|
335
|
+
* - 'json': Return tokens in response body only (default, protocol-agnostic)
|
|
336
|
+
* - 'cookies': Set tokens as httpOnly cookies only (browser web apps)
|
|
337
|
+
* - 'hybrid': Strict hybrid: cookies for web origins, JSON for native; never both
|
|
338
|
+
*
|
|
339
|
+
* Smart defaults (non-configurable unless explicitly overridden):
|
|
340
|
+
* - Cookie names: 'nauth_access_token', 'nauth_refresh_token'
|
|
341
|
+
* - httpOnly: true (always)
|
|
342
|
+
* - secure: true (configurable for localhost/dev)
|
|
343
|
+
* - sameSite: 'strict' (configurable)
|
|
344
|
+
* - path: '/' (configurable)
|
|
345
|
+
*
|
|
346
|
+
* @default { method: 'json' }
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* // Minimal (99% of use cases)
|
|
350
|
+
* tokenDelivery: { method: 'cookies' }
|
|
351
|
+
*
|
|
352
|
+
* // With overrides (rare)
|
|
353
|
+
* tokenDelivery: {
|
|
354
|
+
* method: 'hybrid',
|
|
355
|
+
* cookieOptions: {
|
|
356
|
+
* secure: false, // For localhost development
|
|
357
|
+
* domain: '.myapp.com', // For subdomain sharing
|
|
358
|
+
* }
|
|
359
|
+
* }
|
|
360
|
+
*/
|
|
29
361
|
tokenDelivery?: TokenDeliveryConfig;
|
|
362
|
+
/**
|
|
363
|
+
* Challenge configuration
|
|
364
|
+
*
|
|
365
|
+
* Controls challenge session behavior for authentication challenges
|
|
366
|
+
* (email verification, phone verification, MFA challenges, etc.)
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```typescript
|
|
370
|
+
* challenge: {
|
|
371
|
+
* maxAttempts: 3 // Default: 3 attempts (4th failure causes error)
|
|
372
|
+
* }
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
30
375
|
challenge?: ChallengeConfig;
|
|
376
|
+
/**
|
|
377
|
+
* Geolocation configuration
|
|
378
|
+
*
|
|
379
|
+
* Configures IP geolocation using MaxMind GeoIP2 database files.
|
|
380
|
+
* Platform-agnostic - works on all platforms where Node.js runs.
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* ```typescript
|
|
384
|
+
* geoLocation: {
|
|
385
|
+
* maxMind: {
|
|
386
|
+
* licenseKey: process.env.MAXMIND_LICENSE_KEY,
|
|
387
|
+
* accountId: parseInt(process.env.MAXMIND_ACCOUNT_ID || '0'),
|
|
388
|
+
* // dbPath not set = uses system temp directory
|
|
389
|
+
* }
|
|
390
|
+
* }
|
|
391
|
+
* ```
|
|
392
|
+
*/
|
|
31
393
|
geoLocation?: GeoLocationConfig;
|
|
32
394
|
}
|
|
395
|
+
/**
|
|
396
|
+
* NAuth logger configuration with PII redaction options
|
|
397
|
+
*/
|
|
33
398
|
export interface NAuthLoggerConfig {
|
|
399
|
+
/**
|
|
400
|
+
* Logger instance (NestJS Logger, Winston, Pino, or custom)
|
|
401
|
+
*/
|
|
34
402
|
instance: LoggerService;
|
|
403
|
+
/**
|
|
404
|
+
* Enable PII redaction (default: true)
|
|
405
|
+
* Automatically redacts emails, IPs, tokens, phone numbers, etc.
|
|
406
|
+
*
|
|
407
|
+
* WARNING: Only disable for debugging in development
|
|
408
|
+
*/
|
|
35
409
|
enablePiiRedaction?: boolean;
|
|
410
|
+
/**
|
|
411
|
+
* Optional: Control minimum log level
|
|
412
|
+
* If not set, all log methods will be called (logger decides what to output)
|
|
413
|
+
*/
|
|
36
414
|
logLevel?: 'error' | 'warn' | 'log' | 'debug' | 'verbose';
|
|
37
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* Logger interface compatible with NestJS LoggerService
|
|
418
|
+
* Supports any logger that implements these methods
|
|
419
|
+
*/
|
|
38
420
|
export interface LoggerService {
|
|
39
421
|
log(message: any, ...optionalParams: any[]): any;
|
|
40
422
|
error(message: any, ...optionalParams: any[]): any;
|
|
@@ -43,205 +425,1392 @@ export interface LoggerService {
|
|
|
43
425
|
verbose?(message: any, ...optionalParams: any[]): any;
|
|
44
426
|
}
|
|
45
427
|
export interface JwtConfig {
|
|
428
|
+
/**
|
|
429
|
+
* JWT algorithm
|
|
430
|
+
*
|
|
431
|
+
* - HS256/HS384/HS512: HMAC with SHA (symmetric key, default: HS256)
|
|
432
|
+
* - RS256/RS384/RS512: RSA with SHA (asymmetric key pair)
|
|
433
|
+
*/
|
|
46
434
|
algorithm?: 'HS256' | 'HS384' | 'HS512' | 'RS256' | 'RS384' | 'RS512';
|
|
435
|
+
/**
|
|
436
|
+
* Access token configuration
|
|
437
|
+
*/
|
|
47
438
|
accessToken: AccessTokenConfig;
|
|
439
|
+
/**
|
|
440
|
+
* Refresh token configuration
|
|
441
|
+
*/
|
|
48
442
|
refreshToken: RefreshTokenConfig;
|
|
443
|
+
/**
|
|
444
|
+
* Token issuer
|
|
445
|
+
*/
|
|
49
446
|
issuer?: string;
|
|
447
|
+
/**
|
|
448
|
+
* Token audience
|
|
449
|
+
*/
|
|
50
450
|
audience?: string | string[];
|
|
51
451
|
}
|
|
52
452
|
export interface AccessTokenConfig {
|
|
453
|
+
/**
|
|
454
|
+
* Secret key for symmetric algorithms (HS256/HS384/HS512)
|
|
455
|
+
* Base64-encoded string
|
|
456
|
+
*/
|
|
53
457
|
secret?: string;
|
|
458
|
+
/**
|
|
459
|
+
* Private key for asymmetric algorithms (RS256/RS384/RS512)
|
|
460
|
+
* PEM-encoded private key
|
|
461
|
+
*/
|
|
54
462
|
privateKey?: string;
|
|
463
|
+
/**
|
|
464
|
+
* Public key for asymmetric algorithms (RS256/RS384/RS512)
|
|
465
|
+
* PEM-encoded public key
|
|
466
|
+
*/
|
|
55
467
|
publicKey?: string;
|
|
468
|
+
/**
|
|
469
|
+
* Token expiration time (e.g., '15m', '1h', 900)
|
|
470
|
+
*/
|
|
56
471
|
expiresIn: string | number;
|
|
57
472
|
}
|
|
58
473
|
export interface RefreshTokenConfig {
|
|
474
|
+
/**
|
|
475
|
+
* Secret key for signing (typically uses HS256 for refresh tokens)
|
|
476
|
+
* Base64-encoded string
|
|
477
|
+
*/
|
|
59
478
|
secret: string;
|
|
479
|
+
/**
|
|
480
|
+
* Token expiration time (e.g., '30d', '7d')
|
|
481
|
+
*/
|
|
60
482
|
expiresIn: string | number;
|
|
483
|
+
/**
|
|
484
|
+
* Enable token rotation (generate new refresh token on each use)
|
|
485
|
+
*/
|
|
61
486
|
rotation?: boolean;
|
|
487
|
+
/**
|
|
488
|
+
* Enable refresh token reuse detection
|
|
489
|
+
*/
|
|
62
490
|
reuseDetection?: boolean;
|
|
63
491
|
}
|
|
64
492
|
export interface SignupConfig {
|
|
493
|
+
/**
|
|
494
|
+
* Enable user signups
|
|
495
|
+
* If false, signup endpoint will return 403 Forbidden
|
|
496
|
+
*
|
|
497
|
+
* Default: true
|
|
498
|
+
*/
|
|
65
499
|
enabled?: boolean;
|
|
500
|
+
/**
|
|
501
|
+
* Verification method requirement
|
|
502
|
+
*
|
|
503
|
+
* Options:
|
|
504
|
+
* - 'none': No verification required (users can login immediately)
|
|
505
|
+
* - 'email': Email verification required before login (default)
|
|
506
|
+
* - 'phone': Phone verification required before login
|
|
507
|
+
* - 'both': BOTH email AND phone verification required
|
|
508
|
+
*
|
|
509
|
+
* Default: 'email'
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```typescript
|
|
513
|
+
* // No verification (auto-activate)
|
|
514
|
+
* signup: { verificationMethod: 'none' }
|
|
515
|
+
*
|
|
516
|
+
* // Email only (default)
|
|
517
|
+
* signup: { verificationMethod: 'email' }
|
|
518
|
+
*
|
|
519
|
+
* // Both required
|
|
520
|
+
* signup: { verificationMethod: 'both' }
|
|
521
|
+
* ```
|
|
522
|
+
*/
|
|
66
523
|
verificationMethod?: 'none' | 'email' | 'phone' | 'both';
|
|
524
|
+
/**
|
|
525
|
+
* Allow duplicate phone numbers
|
|
526
|
+
* If true, multiple users can have the same phone number
|
|
527
|
+
* Phone verification will be user-specific (requires user sub)
|
|
528
|
+
*
|
|
529
|
+
* Default: false
|
|
530
|
+
*
|
|
531
|
+
* @example
|
|
532
|
+
* ```typescript
|
|
533
|
+
* // Allow shared phone numbers (family accounts, etc.)
|
|
534
|
+
* signup: { allowDuplicatePhones: true }
|
|
535
|
+
* ```
|
|
536
|
+
*/
|
|
67
537
|
allowDuplicatePhones?: boolean;
|
|
538
|
+
/**
|
|
539
|
+
* Email verification settings
|
|
540
|
+
* Only relevant when verificationMethod is 'email' or 'both'
|
|
541
|
+
*/
|
|
68
542
|
emailVerification?: {
|
|
543
|
+
/**
|
|
544
|
+
* Code expiry in seconds
|
|
545
|
+
* @default 3600 (1 hour)
|
|
546
|
+
*/
|
|
69
547
|
expiresIn?: number;
|
|
548
|
+
/**
|
|
549
|
+
* Delay between resend requests in seconds
|
|
550
|
+
* Prevents users from requesting codes too frequently
|
|
551
|
+
* @default 60
|
|
552
|
+
*/
|
|
70
553
|
resendDelay?: number;
|
|
554
|
+
/**
|
|
555
|
+
* Maximum email verification codes per time window
|
|
556
|
+
* Prevents email abuse and rate limiting
|
|
557
|
+
* @default 3
|
|
558
|
+
*/
|
|
71
559
|
rateLimitMax?: number;
|
|
560
|
+
/**
|
|
561
|
+
* Rate limit time window in seconds
|
|
562
|
+
* The time period over which rateLimitMax applies
|
|
563
|
+
* @default 3600 (1 hour)
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* ```typescript
|
|
567
|
+
* // Allow 5 emails per hour
|
|
568
|
+
* rateLimitMax: 5,
|
|
569
|
+
* rateLimitWindow: 3600, // 1 hour
|
|
570
|
+
*
|
|
571
|
+
* // Allow 3 emails per 15 minutes (stricter)
|
|
572
|
+
* rateLimitMax: 3,
|
|
573
|
+
* rateLimitWindow: 900, // 15 minutes
|
|
574
|
+
* ```
|
|
575
|
+
*/
|
|
72
576
|
rateLimitWindow?: number;
|
|
577
|
+
/**
|
|
578
|
+
* Maximum verification attempts per user per time window
|
|
579
|
+
* Limits how many times a user can attempt to verify their email with a code
|
|
580
|
+
* @default 10
|
|
581
|
+
*/
|
|
73
582
|
maxAttemptsPerUser?: number;
|
|
583
|
+
/**
|
|
584
|
+
* Maximum verification attempts per IP per time window
|
|
585
|
+
* Limits how many verification attempts can be made from a single IP address
|
|
586
|
+
* @default 20
|
|
587
|
+
*/
|
|
74
588
|
maxAttemptsPerIP?: number;
|
|
589
|
+
/**
|
|
590
|
+
* Verification attempt rate limit window in seconds
|
|
591
|
+
* The time period over which maxAttemptsPerUser and maxAttemptsPerIP apply
|
|
592
|
+
* @default 3600 (1 hour)
|
|
593
|
+
*/
|
|
75
594
|
attemptWindow?: number;
|
|
76
595
|
};
|
|
596
|
+
/**
|
|
597
|
+
* Phone verification settings
|
|
598
|
+
* Only relevant when verificationMethod is 'phone' or 'both'
|
|
599
|
+
*/
|
|
77
600
|
phoneVerification?: {
|
|
601
|
+
/**
|
|
602
|
+
* OTP code length
|
|
603
|
+
* @default 6
|
|
604
|
+
*/
|
|
78
605
|
codeLength?: number;
|
|
606
|
+
/**
|
|
607
|
+
* Code expiry in seconds
|
|
608
|
+
* @default 300 (5 minutes)
|
|
609
|
+
*/
|
|
79
610
|
expiresIn?: number;
|
|
611
|
+
/**
|
|
612
|
+
* Maximum verification attempts per code
|
|
613
|
+
* @default 3
|
|
614
|
+
*/
|
|
80
615
|
maxAttempts?: number;
|
|
616
|
+
/**
|
|
617
|
+
* Delay between resend requests in seconds
|
|
618
|
+
* Prevents users from requesting codes too frequently
|
|
619
|
+
* @default 60
|
|
620
|
+
*/
|
|
81
621
|
resendDelay?: number;
|
|
622
|
+
/**
|
|
623
|
+
* Maximum SMS verification codes per time window
|
|
624
|
+
* Prevents SMS abuse and rate limiting
|
|
625
|
+
* @default 3
|
|
626
|
+
*/
|
|
82
627
|
rateLimitMax?: number;
|
|
628
|
+
/**
|
|
629
|
+
* Rate limit time window in seconds
|
|
630
|
+
* The time period over which rateLimitMax applies
|
|
631
|
+
* @default 3600 (1 hour)
|
|
632
|
+
*
|
|
633
|
+
* @example
|
|
634
|
+
* ```typescript
|
|
635
|
+
* // Allow 5 SMS codes per hour
|
|
636
|
+
* rateLimitMax: 5,
|
|
637
|
+
* rateLimitWindow: 3600, // 1 hour
|
|
638
|
+
*
|
|
639
|
+
* // Allow 3 SMS codes per 15 minutes (stricter)
|
|
640
|
+
* rateLimitMax: 3,
|
|
641
|
+
* rateLimitWindow: 900, // 15 minutes
|
|
642
|
+
* ```
|
|
643
|
+
*/
|
|
83
644
|
rateLimitWindow?: number;
|
|
645
|
+
/**
|
|
646
|
+
* Maximum verification attempts per user per time window
|
|
647
|
+
* Limits how many times a user can attempt to verify their phone with a code
|
|
648
|
+
* @default 10
|
|
649
|
+
*/
|
|
84
650
|
maxAttemptsPerUser?: number;
|
|
651
|
+
/**
|
|
652
|
+
* Maximum verification attempts per IP per time window
|
|
653
|
+
* Limits how many verification attempts can be made from a single IP address
|
|
654
|
+
* @default 20
|
|
655
|
+
*/
|
|
85
656
|
maxAttemptsPerIP?: number;
|
|
657
|
+
/**
|
|
658
|
+
* Verification attempt rate limit window in seconds
|
|
659
|
+
* The time period over which maxAttemptsPerUser and maxAttemptsPerIP apply
|
|
660
|
+
* @default 3600 (1 hour)
|
|
661
|
+
*/
|
|
86
662
|
attemptWindow?: number;
|
|
87
663
|
};
|
|
88
664
|
}
|
|
89
665
|
export interface LoginConfig {
|
|
666
|
+
/**
|
|
667
|
+
* Identifier type for login
|
|
668
|
+
*
|
|
669
|
+
* Controls which identifier types are accepted during login:
|
|
670
|
+
* - 'email': Only email addresses accepted
|
|
671
|
+
* - 'username': Only usernames accepted
|
|
672
|
+
* - 'phone': Only phone numbers accepted
|
|
673
|
+
* - 'email_or_username': Both email and username accepted (phone excluded)
|
|
674
|
+
*
|
|
675
|
+
* @default undefined (all types accepted: email, username, phone)
|
|
676
|
+
*
|
|
677
|
+
* @example
|
|
678
|
+
* ```typescript
|
|
679
|
+
* // Only allow email login
|
|
680
|
+
* login: {
|
|
681
|
+
* identifierType: 'email'
|
|
682
|
+
* }
|
|
683
|
+
*
|
|
684
|
+
* // Allow email or username (not phone)
|
|
685
|
+
* login: {
|
|
686
|
+
* identifierType: 'email_or_username'
|
|
687
|
+
* }
|
|
688
|
+
* ```
|
|
689
|
+
*/
|
|
90
690
|
identifierType?: 'email' | 'username' | 'phone' | 'email_or_username';
|
|
91
691
|
}
|
|
92
692
|
export interface PasswordConfig {
|
|
693
|
+
/**
|
|
694
|
+
* Minimum password length
|
|
695
|
+
*/
|
|
93
696
|
minLength?: number;
|
|
697
|
+
/**
|
|
698
|
+
* Maximum password length
|
|
699
|
+
*/
|
|
94
700
|
maxLength?: number;
|
|
701
|
+
/**
|
|
702
|
+
* Require uppercase letters
|
|
703
|
+
*/
|
|
95
704
|
requireUppercase?: boolean;
|
|
705
|
+
/**
|
|
706
|
+
* Require lowercase letters
|
|
707
|
+
*/
|
|
96
708
|
requireLowercase?: boolean;
|
|
709
|
+
/**
|
|
710
|
+
* Require numbers
|
|
711
|
+
*/
|
|
97
712
|
requireNumbers?: boolean;
|
|
713
|
+
/**
|
|
714
|
+
* Require special characters
|
|
715
|
+
*/
|
|
98
716
|
requireSpecialChars?: boolean;
|
|
717
|
+
/**
|
|
718
|
+
* Allowed special characters
|
|
719
|
+
*/
|
|
99
720
|
specialChars?: string;
|
|
721
|
+
/**
|
|
722
|
+
* Prevent common passwords
|
|
723
|
+
*/
|
|
100
724
|
preventCommon?: boolean;
|
|
725
|
+
/**
|
|
726
|
+
* Prevent username/email in password
|
|
727
|
+
*/
|
|
101
728
|
preventUserInfo?: boolean;
|
|
729
|
+
/**
|
|
730
|
+
* Password history count (prevent reuse)
|
|
731
|
+
*/
|
|
102
732
|
historyCount?: number;
|
|
733
|
+
/**
|
|
734
|
+
* Password expiry in days (0 = disabled)
|
|
735
|
+
*/
|
|
103
736
|
expiryDays?: number;
|
|
737
|
+
/**
|
|
738
|
+
* Password reset (account recovery) configuration
|
|
739
|
+
*
|
|
740
|
+
* Controls forgot-password verification code behavior (delivery is handled by the
|
|
741
|
+
* configured email/SMS providers).
|
|
742
|
+
*
|
|
743
|
+
* Note: Defaults are applied in service layer when not provided.
|
|
744
|
+
*/
|
|
104
745
|
passwordReset?: {
|
|
746
|
+
/**
|
|
747
|
+
* Verification code length
|
|
748
|
+
* @default 6
|
|
749
|
+
*/
|
|
105
750
|
codeLength?: number;
|
|
751
|
+
/**
|
|
752
|
+
* Code expiry in seconds
|
|
753
|
+
* @default 900 (15 minutes)
|
|
754
|
+
*/
|
|
106
755
|
expiresIn?: number;
|
|
756
|
+
/**
|
|
757
|
+
* Maximum reset requests per time window
|
|
758
|
+
* @default 3
|
|
759
|
+
*/
|
|
107
760
|
rateLimitMax?: number;
|
|
761
|
+
/**
|
|
762
|
+
* Rate limit time window in seconds
|
|
763
|
+
* @default 3600 (1 hour)
|
|
764
|
+
*/
|
|
108
765
|
rateLimitWindow?: number;
|
|
766
|
+
/**
|
|
767
|
+
* Maximum code verification attempts per code
|
|
768
|
+
* @default 3
|
|
769
|
+
*/
|
|
109
770
|
maxAttempts?: number;
|
|
110
771
|
};
|
|
111
772
|
}
|
|
112
773
|
export interface LockoutConfig {
|
|
774
|
+
/**
|
|
775
|
+
* Enable IP-based account lockout
|
|
776
|
+
*
|
|
777
|
+
* SECURITY: Uses IP addresses instead of user identifiers to prevent
|
|
778
|
+
* attackers from locking out legitimate users by guessing their email/username.
|
|
779
|
+
*/
|
|
113
780
|
enabled?: boolean;
|
|
781
|
+
/**
|
|
782
|
+
* Maximum failed login attempts per IP address
|
|
783
|
+
*/
|
|
114
784
|
maxAttempts?: number;
|
|
785
|
+
/**
|
|
786
|
+
* IP lockout duration in seconds
|
|
787
|
+
*/
|
|
115
788
|
duration?: number;
|
|
789
|
+
/**
|
|
790
|
+
* Reset IP counter on successful login
|
|
791
|
+
*/
|
|
116
792
|
resetOnSuccess?: boolean;
|
|
117
793
|
}
|
|
118
794
|
export interface SessionConfig {
|
|
795
|
+
/**
|
|
796
|
+
* Maximum concurrent sessions per user
|
|
797
|
+
*/
|
|
119
798
|
maxConcurrent?: number;
|
|
799
|
+
/**
|
|
800
|
+
* Disallow multiple concurrent sessions
|
|
801
|
+
* When enabled, only one active session is allowed per user.
|
|
802
|
+
* When a user logs in on a new device/session, all other sessions are automatically logged out.
|
|
803
|
+
*
|
|
804
|
+
* @default false
|
|
805
|
+
*
|
|
806
|
+
* @example
|
|
807
|
+
* ```typescript
|
|
808
|
+
* // Only allow one active session per user
|
|
809
|
+
* session: {
|
|
810
|
+
* disallowMultipleSessions: true
|
|
811
|
+
* }
|
|
812
|
+
*
|
|
813
|
+
* // Allow multiple sessions (default)
|
|
814
|
+
* session: {
|
|
815
|
+
* disallowMultipleSessions: false
|
|
816
|
+
* }
|
|
817
|
+
* ```
|
|
818
|
+
*/
|
|
120
819
|
disallowMultipleSessions?: boolean;
|
|
820
|
+
/**
|
|
821
|
+
* Maximum session lifetime (hard limit)
|
|
822
|
+
*
|
|
823
|
+
* This is the maximum duration a session can exist, regardless of refresh token activity.
|
|
824
|
+
* Even if a user actively refreshes their tokens daily, after this time they must re-authenticate.
|
|
825
|
+
*
|
|
826
|
+
* This provides a security boundary to force periodic re-authentication, preventing
|
|
827
|
+
* indefinite sessions even for very active users.
|
|
828
|
+
*
|
|
829
|
+
* Format: String (e.g., '30d', '7d', '90d', '5h') or number (seconds)
|
|
830
|
+
* - 's' = seconds
|
|
831
|
+
* - 'm' = minutes
|
|
832
|
+
* - 'h' = hours
|
|
833
|
+
* - 'd' = days
|
|
834
|
+
*
|
|
835
|
+
* @default '30d' (30 days)
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* ```typescript
|
|
839
|
+
* // 30 days (default)
|
|
840
|
+
* session: {
|
|
841
|
+
* maxLifetime: '30d'
|
|
842
|
+
* }
|
|
843
|
+
*
|
|
844
|
+
* // 90 days (more lenient)
|
|
845
|
+
* session: {
|
|
846
|
+
* maxLifetime: '90d'
|
|
847
|
+
* }
|
|
848
|
+
*
|
|
849
|
+
* // 7 days (stricter)
|
|
850
|
+
* session: {
|
|
851
|
+
* maxLifetime: '7d'
|
|
852
|
+
* }
|
|
853
|
+
*
|
|
854
|
+
* // Using seconds
|
|
855
|
+
* session: {
|
|
856
|
+
* maxLifetime: 2592000 // 30 days in seconds
|
|
857
|
+
* }
|
|
858
|
+
* ```
|
|
859
|
+
*/
|
|
121
860
|
maxLifetime?: string | number;
|
|
122
861
|
}
|
|
123
862
|
export interface SecurityConfig {
|
|
863
|
+
/**
|
|
864
|
+
* CSRF Protection Configuration
|
|
865
|
+
*
|
|
866
|
+
* WARNING: SECURITY - CSRF protection is REQUIRED when using cookie-based token delivery
|
|
867
|
+
* (tokenDelivery.method === 'cookies' or 'hybrid' with web origins).
|
|
868
|
+
*
|
|
869
|
+
* CSRF protection prevents Cross-Site Request Forgery attacks when tokens are stored in cookies.
|
|
870
|
+
* The CSRF Guard is automatically registered when tokenDelivery.method === 'cookies' or 'hybrid'.
|
|
871
|
+
* CSRF tokens are automatically generated and set as cookies on login/refresh.
|
|
872
|
+
*
|
|
873
|
+
* Frontend must:
|
|
874
|
+
* 1. Read CSRF token from cookie (cookieName)
|
|
875
|
+
* 2. Send CSRF token in request header (headerName) for state-changing requests (POST, PUT, DELETE, PATCH)
|
|
876
|
+
* 3. Skip for safe methods (GET, HEAD, OPTIONS) - these don't require CSRF token
|
|
877
|
+
*
|
|
878
|
+
* CSRF protection is NOT required for JSON token delivery (Bearer tokens in headers are CSRF-safe).
|
|
879
|
+
*
|
|
880
|
+
* @example
|
|
881
|
+
* ```typescript
|
|
882
|
+
* // CSRF configuration (required for cookie-based token delivery)
|
|
883
|
+
* security: {
|
|
884
|
+
* csrf: {
|
|
885
|
+
* cookieName: 'csrf-token',
|
|
886
|
+
* headerName: 'x-csrf-token',
|
|
887
|
+
* tokenLength: 32,
|
|
888
|
+
* excludedPaths: ['/webhook'] // Exclude webhook endpoints
|
|
889
|
+
* }
|
|
890
|
+
* }
|
|
891
|
+
* ```
|
|
892
|
+
*/
|
|
124
893
|
csrf?: {
|
|
894
|
+
/**
|
|
895
|
+
* Name of the CSRF cookie
|
|
896
|
+
*
|
|
897
|
+
* If not provided, defaults to `${tokenDelivery.cookieNamePrefix || 'nauth_'}csrf_token`
|
|
898
|
+
* (e.g., 'nauth_csrf_token' with default prefix).
|
|
899
|
+
*
|
|
900
|
+
* The prefix ensures consistency with other auth cookie names and avoids conflicts.
|
|
901
|
+
*
|
|
902
|
+
* @default `${tokenDelivery.cookieNamePrefix || 'nauth_'}csrf_token`
|
|
903
|
+
*/
|
|
125
904
|
cookieName?: string;
|
|
905
|
+
/**
|
|
906
|
+
* Name of the CSRF header to check
|
|
907
|
+
* Default: 'x-csrf-token'
|
|
908
|
+
*/
|
|
126
909
|
headerName?: string;
|
|
910
|
+
/**
|
|
911
|
+
* Length of CSRF token in bytes
|
|
912
|
+
* Default: 32 (256 bits)
|
|
913
|
+
*/
|
|
127
914
|
tokenLength?: number;
|
|
915
|
+
/**
|
|
916
|
+
* Excluded paths (no CSRF check)
|
|
917
|
+
* Useful for webhook endpoints or public APIs
|
|
918
|
+
* Default: []
|
|
919
|
+
*
|
|
920
|
+
* @example
|
|
921
|
+
* excludedPaths: ['/webhook', '/public-api']
|
|
922
|
+
*/
|
|
128
923
|
excludedPaths?: string[];
|
|
924
|
+
/**
|
|
925
|
+
* Cookie options for CSRF token
|
|
926
|
+
* Default: { secure: true, sameSite: 'strict' }
|
|
927
|
+
*
|
|
928
|
+
* Note: httpOnly is always false (hardcoded) - CSRF token must be readable by JavaScript
|
|
929
|
+
*/
|
|
129
930
|
cookieOptions?: {
|
|
931
|
+
/**
|
|
932
|
+
* Secure cookies (HTTPS only)
|
|
933
|
+
* Set to false for localhost development
|
|
934
|
+
* @default true
|
|
935
|
+
*/
|
|
130
936
|
secure?: boolean;
|
|
937
|
+
/**
|
|
938
|
+
* SameSite cookie attribute
|
|
939
|
+
* - 'strict': Most secure, cookies only sent on same-site requests
|
|
940
|
+
* - 'lax': Cookies sent on same-site + top-level navigation (e.g., link from Google)
|
|
941
|
+
* - 'none': Cookies sent on all requests (requires secure: true)
|
|
942
|
+
* @default 'strict'
|
|
943
|
+
*/
|
|
131
944
|
sameSite?: 'strict' | 'lax' | 'none';
|
|
945
|
+
/**
|
|
946
|
+
* Cookie domain (for subdomain sharing)
|
|
947
|
+
* @example '.dev1.noorix.com' to share across subdomains
|
|
948
|
+
*/
|
|
132
949
|
domain?: string;
|
|
950
|
+
/**
|
|
951
|
+
* Cookie path
|
|
952
|
+
* @default '/'
|
|
953
|
+
*/
|
|
133
954
|
path?: string;
|
|
134
955
|
};
|
|
135
956
|
};
|
|
136
957
|
}
|
|
137
958
|
export interface LifecycleHooks {
|
|
959
|
+
/**
|
|
960
|
+
* Before signup hook
|
|
961
|
+
*
|
|
962
|
+
* Allows consumer applications to implement custom checks before signup proceeds
|
|
963
|
+
* (e.g., denylist, invite-only signups, external validation).
|
|
964
|
+
*
|
|
965
|
+
* Return `false` to block signup.
|
|
966
|
+
*/
|
|
138
967
|
beforeSignup?: (dto: unknown) => Promise<void | false>;
|
|
968
|
+
/**
|
|
969
|
+
* After signup hook
|
|
970
|
+
*/
|
|
139
971
|
afterSignup?: (user: any, metadata?: {
|
|
140
972
|
requiresVerification?: boolean;
|
|
141
973
|
}) => Promise<void>;
|
|
974
|
+
/**
|
|
975
|
+
* Before login hook
|
|
976
|
+
*
|
|
977
|
+
* Allows consumer applications to implement custom checks before login proceeds
|
|
978
|
+
* (e.g., denylist, maintenance windows, external risk checks).
|
|
979
|
+
*
|
|
980
|
+
* Return `false` to block login.
|
|
981
|
+
*/
|
|
142
982
|
beforeLogin?: (identifier: string) => Promise<void | false>;
|
|
143
983
|
afterLogin?: (user: any, session: any) => Promise<void>;
|
|
984
|
+
/**
|
|
985
|
+
* After login failed hook
|
|
986
|
+
*/
|
|
144
987
|
afterLoginFailed?: (identifier: string, reason: string) => Promise<void>;
|
|
988
|
+
/**
|
|
989
|
+
* Before password change hook
|
|
990
|
+
*/
|
|
145
991
|
beforePasswordChange?: (userId: string, oldPassword: string) => Promise<void | false>;
|
|
992
|
+
/**
|
|
993
|
+
* After password change hook
|
|
994
|
+
*/
|
|
146
995
|
afterPasswordChange?: (userId: string) => Promise<void>;
|
|
996
|
+
/**
|
|
997
|
+
* Before account lock hook
|
|
998
|
+
*/
|
|
147
999
|
beforeAccountLock?: (userId: string, reason: string) => Promise<void | false>;
|
|
1000
|
+
/**
|
|
1001
|
+
* After account lock hook
|
|
1002
|
+
*/
|
|
148
1003
|
afterAccountLock?: (userId: string, reason: string) => Promise<void>;
|
|
1004
|
+
/**
|
|
1005
|
+
* Adaptive MFA risk detected hook
|
|
1006
|
+
*
|
|
1007
|
+
* Called when adaptive MFA evaluates a login attempt and detects risk.
|
|
1008
|
+
* Allows consumer app to send custom notifications, log to external systems,
|
|
1009
|
+
* trigger security workflows, etc.
|
|
1010
|
+
*
|
|
1011
|
+
* This hook is called BEFORE the action is enforced (allow/require_mfa/block).
|
|
1012
|
+
* Return false to override the adaptive decision and allow sign-in.
|
|
1013
|
+
*
|
|
1014
|
+
* @param payload - Rich context about the risk event
|
|
1015
|
+
* @returns void to continue with configured action, false to override and allow
|
|
1016
|
+
*
|
|
1017
|
+
* @example Email notification
|
|
1018
|
+
* ```typescript
|
|
1019
|
+
* onAdaptiveMFATriggered: async (payload) => {
|
|
1020
|
+
* if (payload.riskLevel === 'high') {
|
|
1021
|
+
* await emailService.send({
|
|
1022
|
+
* to: payload.user.email,
|
|
1023
|
+
* subject: 'Suspicious sign-in attempt detected',
|
|
1024
|
+
* template: 'security-alert',
|
|
1025
|
+
* data: {
|
|
1026
|
+
* location: `${payload.clientInfo.ipCity}, ${payload.clientInfo.ipCountry}`,
|
|
1027
|
+
* device: payload.clientInfo.deviceName,
|
|
1028
|
+
* time: new Date().toISOString(),
|
|
1029
|
+
* riskFactors: payload.riskFactors.join(', '),
|
|
1030
|
+
* }
|
|
1031
|
+
* });
|
|
1032
|
+
* }
|
|
1033
|
+
* }
|
|
1034
|
+
* ```
|
|
1035
|
+
*
|
|
1036
|
+
* @example Slack notification to security team
|
|
1037
|
+
* ```typescript
|
|
1038
|
+
* onAdaptiveMFATriggered: async (payload) => {
|
|
1039
|
+
* if (payload.action === 'block_signin') {
|
|
1040
|
+
* await slackService.postMessage({
|
|
1041
|
+
* channel: '#security-alerts',
|
|
1042
|
+
* text: `High-risk sign-in blocked for ${payload.user.email}`,
|
|
1043
|
+
* attachments: [{
|
|
1044
|
+
* fields: [
|
|
1045
|
+
* { title: 'Risk Score', value: payload.riskScore.toString() },
|
|
1046
|
+
* { title: 'Risk Factors', value: payload.riskFactors.join(', ') },
|
|
1047
|
+
* { title: 'Location', value: payload.clientInfo.ipCountry },
|
|
1048
|
+
* ]
|
|
1049
|
+
* }]
|
|
1050
|
+
* });
|
|
1051
|
+
* }
|
|
1052
|
+
* }
|
|
1053
|
+
* ```
|
|
1054
|
+
*
|
|
1055
|
+
* @example Custom workflow with admin review
|
|
1056
|
+
* ```typescript
|
|
1057
|
+
* onAdaptiveMFATriggered: async (payload) => {
|
|
1058
|
+
* if (payload.riskScore > 80) {
|
|
1059
|
+
* // Create security review ticket
|
|
1060
|
+
* await securityReviewService.createTicket({
|
|
1061
|
+
* userId: payload.user.sub,
|
|
1062
|
+
* riskScore: payload.riskScore,
|
|
1063
|
+
* riskFactors: payload.riskFactors,
|
|
1064
|
+
* requiresManualReview: true,
|
|
1065
|
+
* });
|
|
1066
|
+
*
|
|
1067
|
+
* // Send push notification to admins
|
|
1068
|
+
* await adminNotificationService.alert({
|
|
1069
|
+
* type: 'high_risk_signin',
|
|
1070
|
+
* userId: payload.user.sub,
|
|
1071
|
+
* });
|
|
1072
|
+
* }
|
|
1073
|
+
* }
|
|
1074
|
+
* ```
|
|
1075
|
+
*/
|
|
149
1076
|
onAdaptiveMFATriggered?: (payload: AdaptiveMFARiskEventPayload) => Promise<void | false>;
|
|
1077
|
+
/**
|
|
1078
|
+
* Sign-in blocked hook
|
|
1079
|
+
*
|
|
1080
|
+
* Called when a sign-in is blocked due to high risk.
|
|
1081
|
+
* Allows consumer app to implement custom blocking workflows,
|
|
1082
|
+
* manual review processes, or admin notifications.
|
|
1083
|
+
*
|
|
1084
|
+
* @param payload - Context about the blocked sign-in
|
|
1085
|
+
*
|
|
1086
|
+
* @example Create manual review case
|
|
1087
|
+
* ```typescript
|
|
1088
|
+
* onSignInBlocked: async (payload) => {
|
|
1089
|
+
* await adminDashboardService.createReviewCase({
|
|
1090
|
+
* userId: payload.user.sub,
|
|
1091
|
+
* reason: 'High-risk adaptive MFA',
|
|
1092
|
+
* riskScore: payload.riskScore,
|
|
1093
|
+
* requiresAction: true,
|
|
1094
|
+
* });
|
|
1095
|
+
* }
|
|
1096
|
+
* ```
|
|
1097
|
+
*/
|
|
150
1098
|
onSignInBlocked?: (payload: SignInBlockedPayload) => Promise<void>;
|
|
151
1099
|
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Email Verification Configuration
|
|
1102
|
+
*/
|
|
152
1103
|
export interface EmailConfig {
|
|
1104
|
+
/**
|
|
1105
|
+
* Application name (used in email templates)
|
|
1106
|
+
*
|
|
1107
|
+
* @example 'My Application'
|
|
1108
|
+
*/
|
|
153
1109
|
appName?: string;
|
|
1110
|
+
/**
|
|
1111
|
+
* Company name (used in email footer)
|
|
1112
|
+
*
|
|
1113
|
+
* @example 'My Company Inc.'
|
|
1114
|
+
*/
|
|
154
1115
|
companyName?: string;
|
|
1116
|
+
/**
|
|
1117
|
+
* Logo URL for email templates
|
|
1118
|
+
*
|
|
1119
|
+
* @example 'https://example.com/logo.png'
|
|
1120
|
+
*/
|
|
155
1121
|
logoUrl?: string;
|
|
1122
|
+
/**
|
|
1123
|
+
* Support email address (displayed in email footer)
|
|
1124
|
+
*
|
|
1125
|
+
* @example 'support@example.com'
|
|
1126
|
+
*/
|
|
156
1127
|
supportEmail?: string;
|
|
1128
|
+
/**
|
|
1129
|
+
* Dashboard URL (used in welcome emails)
|
|
1130
|
+
*
|
|
1131
|
+
* @example 'https://app.example.com/dashboard'
|
|
1132
|
+
*/
|
|
157
1133
|
dashboardUrl?: string;
|
|
1134
|
+
/**
|
|
1135
|
+
* Brand color (hex code, used in email templates)
|
|
1136
|
+
*
|
|
1137
|
+
* @example '#4f46e5'
|
|
1138
|
+
*/
|
|
158
1139
|
brandColor?: string;
|
|
1140
|
+
/**
|
|
1141
|
+
* Custom footer disclaimer text
|
|
1142
|
+
*
|
|
1143
|
+
* If not provided, uses default professional disclaimer.
|
|
1144
|
+
*
|
|
1145
|
+
* @example 'This email is confidential. Unsubscribe at any time.'
|
|
1146
|
+
*/
|
|
159
1147
|
footerDisclaimer?: string;
|
|
1148
|
+
/**
|
|
1149
|
+
* Template configuration for email notifications
|
|
1150
|
+
*
|
|
1151
|
+
* Configure custom email templates and global variables for branding.
|
|
1152
|
+
* Templates are validated at startup to ensure required parameters are present.
|
|
1153
|
+
*
|
|
1154
|
+
* Note: Top-level branding fields (appName, companyName, logoUrl, etc.) are automatically
|
|
1155
|
+
* merged into templates.globalVariables. You can override them in globalVariables if needed.
|
|
1156
|
+
*
|
|
1157
|
+
* @example Basic configuration with top-level branding
|
|
1158
|
+
* ```typescript
|
|
1159
|
+
* email: {
|
|
1160
|
+
* appName: process.env.APP_NAME || 'My Application',
|
|
1161
|
+
* companyName: process.env.COMPANY_NAME || 'My Company Inc.',
|
|
1162
|
+
* supportEmail: process.env.SUPPORT_EMAIL || 'support@example.com',
|
|
1163
|
+
* brandColor: '#4f46e5',
|
|
1164
|
+
* logoUrl: 'https://example.com/logo.png'
|
|
1165
|
+
* }
|
|
1166
|
+
* ```
|
|
1167
|
+
*
|
|
1168
|
+
* @example Advanced configuration with global variables
|
|
1169
|
+
* ```typescript
|
|
1170
|
+
* email: {
|
|
1171
|
+
* appName: 'My App',
|
|
1172
|
+
* companyName: 'My Company',
|
|
1173
|
+
* templates: {
|
|
1174
|
+
* globalVariables: {
|
|
1175
|
+
* // These override top-level values if both are provided
|
|
1176
|
+
* appName: 'Custom App Name',
|
|
1177
|
+
* customVar: 'Custom value'
|
|
1178
|
+
* }
|
|
1179
|
+
* }
|
|
1180
|
+
* }
|
|
1181
|
+
* ```
|
|
1182
|
+
*
|
|
1183
|
+
* @example Custom templates with file paths
|
|
1184
|
+
* ```typescript
|
|
1185
|
+
* email: {
|
|
1186
|
+
* templates: {
|
|
1187
|
+
* globalVariables: {
|
|
1188
|
+
* appName: 'My App',
|
|
1189
|
+
* supportEmail: 'support@myapp.com'
|
|
1190
|
+
* },
|
|
1191
|
+
* customTemplates: {
|
|
1192
|
+
* verification: {
|
|
1193
|
+
* htmlPath: './email-templates/verification.html.hbs',
|
|
1194
|
+
* textPath: './email-templates/verification.text.hbs'
|
|
1195
|
+
* // Must include: {{code}}, {{link}}, {{expiryMinutes}}
|
|
1196
|
+
* },
|
|
1197
|
+
* welcome: {
|
|
1198
|
+
* htmlPath: './email-templates/welcome.html.hbs'
|
|
1199
|
+
* // No required params
|
|
1200
|
+
* }
|
|
1201
|
+
* }
|
|
1202
|
+
* }
|
|
1203
|
+
* }
|
|
1204
|
+
* ```
|
|
1205
|
+
*
|
|
1206
|
+
* @example Custom templates with inline content
|
|
1207
|
+
* ```typescript
|
|
1208
|
+
* email: {
|
|
1209
|
+
* templates: {
|
|
1210
|
+
* globalVariables: { appName: 'My App' },
|
|
1211
|
+
* customTemplates: {
|
|
1212
|
+
* welcome: {
|
|
1213
|
+
* subject: 'Welcome to {{appName}}!',
|
|
1214
|
+
* html: `
|
|
1215
|
+
* <h1>Hello {{firstName}}!</h1>
|
|
1216
|
+
* <p>Welcome to {{appName}}!</p>
|
|
1217
|
+
* `,
|
|
1218
|
+
* text: 'Hello {{firstName}}! Welcome to {{appName}}!'
|
|
1219
|
+
* }
|
|
1220
|
+
* }
|
|
1221
|
+
* }
|
|
1222
|
+
* }
|
|
1223
|
+
* ```
|
|
1224
|
+
*/
|
|
160
1225
|
templates?: import('../interfaces/template.interface').TemplateConfig;
|
|
161
1226
|
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Phone Configuration
|
|
1229
|
+
*
|
|
1230
|
+
* Note: Phone verification settings have been moved to signup.phoneVerification
|
|
1231
|
+
* This type is kept for backwards compatibility but is now empty
|
|
1232
|
+
*/
|
|
162
1233
|
export type PhoneConfig = Record<string, never>;
|
|
1234
|
+
/**
|
|
1235
|
+
* Social Login Configuration
|
|
1236
|
+
* Configure OAuth providers for social authentication
|
|
1237
|
+
*/
|
|
163
1238
|
export interface SocialConfig {
|
|
1239
|
+
/**
|
|
1240
|
+
* Google OAuth configuration
|
|
1241
|
+
*/
|
|
164
1242
|
google?: SocialProviderConfig;
|
|
1243
|
+
/**
|
|
1244
|
+
* Apple OAuth configuration
|
|
1245
|
+
*/
|
|
165
1246
|
apple?: SocialProviderConfig;
|
|
1247
|
+
/**
|
|
1248
|
+
* Facebook OAuth configuration
|
|
1249
|
+
*/
|
|
166
1250
|
facebook?: SocialProviderConfig;
|
|
167
1251
|
}
|
|
1252
|
+
/**
|
|
1253
|
+
* Individual social provider configuration
|
|
1254
|
+
*/
|
|
168
1255
|
export interface SocialProviderConfig {
|
|
1256
|
+
/**
|
|
1257
|
+
* Enable this provider
|
|
1258
|
+
* @default false
|
|
1259
|
+
*/
|
|
169
1260
|
enabled?: boolean;
|
|
1261
|
+
/**
|
|
1262
|
+
* OAuth client ID from the provider
|
|
1263
|
+
* Can be a single string or an array for multiple platforms (web, iOS, Android)
|
|
1264
|
+
* Required if enabled
|
|
1265
|
+
*
|
|
1266
|
+
* @example
|
|
1267
|
+
* Single client ID:
|
|
1268
|
+
* clientId: '12345.apps.googleusercontent.com'
|
|
1269
|
+
*
|
|
1270
|
+
* Multiple client IDs (mobile + web):
|
|
1271
|
+
* clientId: [
|
|
1272
|
+
* '12345-web.apps.googleusercontent.com', // Web
|
|
1273
|
+
* '12345-ios.apps.googleusercontent.com', // iOS
|
|
1274
|
+
* '12345-android.apps.googleusercontent.com' // Android
|
|
1275
|
+
* ]
|
|
1276
|
+
*/
|
|
170
1277
|
clientId?: string | string[];
|
|
1278
|
+
/**
|
|
1279
|
+
* OAuth client secret from the provider
|
|
1280
|
+
* Required if enabled
|
|
1281
|
+
*/
|
|
171
1282
|
clientSecret?: string;
|
|
1283
|
+
/**
|
|
1284
|
+
* OAuth callback URL
|
|
1285
|
+
* Must match the URL registered with the provider
|
|
1286
|
+
*
|
|
1287
|
+
* @example
|
|
1288
|
+
* 'https://myapp.com/auth/google/callback'
|
|
1289
|
+
*/
|
|
172
1290
|
callbackUrl?: string;
|
|
1291
|
+
/**
|
|
1292
|
+
* OAuth scopes to request
|
|
1293
|
+
* Provider-specific scopes for accessing user data
|
|
1294
|
+
*
|
|
1295
|
+
* @default ['openid', 'email', 'profile']
|
|
1296
|
+
*/
|
|
173
1297
|
scopes?: string[];
|
|
1298
|
+
/**
|
|
1299
|
+
* Auto-link social accounts to existing users by verified email
|
|
1300
|
+
* If true, when a user signs in with social provider and their email
|
|
1301
|
+
* matches an existing verified user, the accounts will be automatically linked
|
|
1302
|
+
*
|
|
1303
|
+
* @default true
|
|
1304
|
+
*/
|
|
174
1305
|
autoLink?: boolean;
|
|
1306
|
+
/**
|
|
1307
|
+
* Allow creating new users via social signup
|
|
1308
|
+
* If false, only existing users can link their social accounts
|
|
1309
|
+
*
|
|
1310
|
+
* @default true
|
|
1311
|
+
*/
|
|
175
1312
|
allowSignup?: boolean;
|
|
176
1313
|
}
|
|
1314
|
+
/**
|
|
1315
|
+
* Multi-Factor Authentication (MFA) Configuration
|
|
1316
|
+
*
|
|
1317
|
+
* Configure MFA enforcement and allowed methods for your application.
|
|
1318
|
+
* Supports TOTP (authenticator apps), SMS, Email, and Passkeys (WebAuthn).
|
|
1319
|
+
*/
|
|
177
1320
|
export interface MFAConfig {
|
|
1321
|
+
/**
|
|
1322
|
+
* Enable MFA system
|
|
1323
|
+
* @default false
|
|
1324
|
+
*/
|
|
178
1325
|
enabled?: boolean;
|
|
1326
|
+
/**
|
|
1327
|
+
* MFA enforcement policy
|
|
1328
|
+
*
|
|
1329
|
+
* - 'OPTIONAL': Users can choose to enable MFA (default)
|
|
1330
|
+
* - 'REQUIRED': All users must enable MFA within grace period
|
|
1331
|
+
* - 'ADAPTIVE': MFA required based on risk factors (future: conditional triggers)
|
|
1332
|
+
*
|
|
1333
|
+
* @default 'OPTIONAL'
|
|
1334
|
+
*/
|
|
179
1335
|
enforcement?: 'OPTIONAL' | 'REQUIRED' | 'ADAPTIVE';
|
|
1336
|
+
/**
|
|
1337
|
+
* Grace period in days before MFA enforcement applies
|
|
1338
|
+
* Only relevant when enforcement is 'REQUIRED'
|
|
1339
|
+
* Users can login without MFA during this period
|
|
1340
|
+
*
|
|
1341
|
+
* @default 7
|
|
1342
|
+
*/
|
|
180
1343
|
gracePeriod?: number;
|
|
1344
|
+
/**
|
|
1345
|
+
* Allowed MFA methods
|
|
1346
|
+
* Users can register any of these methods
|
|
1347
|
+
*
|
|
1348
|
+
* - 'totp': Time-based One-Time Password (Google Authenticator, Authy, etc.)
|
|
1349
|
+
* - 'sms': SMS verification codes
|
|
1350
|
+
* - 'email': Email verification codes
|
|
1351
|
+
* - 'passkey': WebAuthn/FIDO2 passkeys (biometric, security keys)
|
|
1352
|
+
*
|
|
1353
|
+
* @default [MFAMethod.TOTP, MFAMethod.SMS, MFAMethod.EMAIL, MFAMethod.PASSKEY]
|
|
1354
|
+
*/
|
|
181
1355
|
allowedMethods?: Array<MFADeviceMethod>;
|
|
1356
|
+
/**
|
|
1357
|
+
* Require MFA for social login
|
|
1358
|
+
*
|
|
1359
|
+
* Controls whether MFA is required when users authenticate via
|
|
1360
|
+
* social providers (Google, Apple, Facebook).
|
|
1361
|
+
*
|
|
1362
|
+
* - false: Skip MFA entirely for social login (default - common industry practice)
|
|
1363
|
+
* Social users will NOT be required to setup or verify MFA.
|
|
1364
|
+
* Rationale: Social providers already have strong authentication (often with 2FA),
|
|
1365
|
+
* and OAuth flow itself provides security layer. Better UX with fewer steps.
|
|
1366
|
+
*
|
|
1367
|
+
* - true: Require MFA for social login (higher security)
|
|
1368
|
+
* Social users will be required to setup and verify MFA just like password users.
|
|
1369
|
+
* Rationale: Defense-in-depth. Even if social account is compromised,
|
|
1370
|
+
* attacker cannot access your app without MFA.
|
|
1371
|
+
*
|
|
1372
|
+
* @default false
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* ```typescript
|
|
1376
|
+
* // Skip MFA entirely for social login (default - common practice)
|
|
1377
|
+
* mfa: {
|
|
1378
|
+
* requireForSocialLogin: false
|
|
1379
|
+
* }
|
|
1380
|
+
*
|
|
1381
|
+
* // Require MFA for all logins including social (higher security)
|
|
1382
|
+
* mfa: {
|
|
1383
|
+
* requireForSocialLogin: true
|
|
1384
|
+
* }
|
|
1385
|
+
* ```
|
|
1386
|
+
*/
|
|
182
1387
|
requireForSocialLogin?: boolean;
|
|
1388
|
+
/**
|
|
1389
|
+
* Trusted device behavior
|
|
1390
|
+
*
|
|
1391
|
+
* Controls how devices are marked as trusted for MFA bypass:
|
|
1392
|
+
* - 'never': No trusted device feature (default - most secure)
|
|
1393
|
+
* - 'always': Automatically trust devices after successful login (no user interaction)
|
|
1394
|
+
* - 'user_opt_in': User must explicitly opt-in via API call after login
|
|
1395
|
+
*
|
|
1396
|
+
* When a device is trusted:
|
|
1397
|
+
* - Device token is stored as httpOnly cookie (web) or returned in response (mobile)
|
|
1398
|
+
* - Device token persists across logouts and session expiry
|
|
1399
|
+
* - Device token is independent of refresh token lifecycle
|
|
1400
|
+
* - Trusted devices can skip MFA (if bypassMFAForTrustedDevices is enabled)
|
|
1401
|
+
*
|
|
1402
|
+
* @default 'never'
|
|
1403
|
+
*
|
|
1404
|
+
* @example
|
|
1405
|
+
* ```typescript
|
|
1406
|
+
* // Always trust devices automatically (best UX)
|
|
1407
|
+
* mfa: {
|
|
1408
|
+
* rememberDevices: 'always',
|
|
1409
|
+
* rememberDeviceDays: 30,
|
|
1410
|
+
* bypassMFAForTrustedDevices: true
|
|
1411
|
+
* }
|
|
1412
|
+
*
|
|
1413
|
+
* // User opt-in (user controls trust)
|
|
1414
|
+
* mfa: {
|
|
1415
|
+
* rememberDevices: 'user_opt_in',
|
|
1416
|
+
* rememberDeviceDays: 30,
|
|
1417
|
+
* bypassMFAForTrustedDevices: true
|
|
1418
|
+
* }
|
|
1419
|
+
* ```
|
|
1420
|
+
*/
|
|
183
1421
|
rememberDevices?: 'always' | 'user_opt_in' | 'never';
|
|
1422
|
+
/**
|
|
1423
|
+
* Days to remember trusted devices
|
|
1424
|
+
* Only relevant if rememberDevices is not 'never'
|
|
1425
|
+
*
|
|
1426
|
+
* @default 30
|
|
1427
|
+
*/
|
|
184
1428
|
rememberDeviceDays?: number;
|
|
1429
|
+
/**
|
|
1430
|
+
* Bypass MFA verification for trusted devices
|
|
1431
|
+
*
|
|
1432
|
+
* When true, trusted devices can skip MFA verification.
|
|
1433
|
+
* This only applies when rememberDevices is not 'never' and device is marked as trusted.
|
|
1434
|
+
*
|
|
1435
|
+
* Note: Does NOT apply to ADAPTIVE enforcement mode, which follows its own risk-based logic.
|
|
1436
|
+
*
|
|
1437
|
+
* Security considerations:
|
|
1438
|
+
* - Default false: Require MFA even for trusted devices (more secure)
|
|
1439
|
+
* - true: Skip MFA for trusted devices (better UX, lower security)
|
|
1440
|
+
* - Recommended: Set to false for high-security applications
|
|
1441
|
+
*
|
|
1442
|
+
* @default false
|
|
1443
|
+
*/
|
|
185
1444
|
bypassMFAForTrustedDevices?: boolean;
|
|
1445
|
+
/**
|
|
1446
|
+
* Issuer name for TOTP QR codes
|
|
1447
|
+
* Displayed in authenticator apps
|
|
1448
|
+
*
|
|
1449
|
+
* @default 'nauth-toolkit'
|
|
1450
|
+
*/
|
|
186
1451
|
issuer?: string;
|
|
1452
|
+
/**
|
|
1453
|
+
* TOTP-specific configuration
|
|
1454
|
+
*/
|
|
187
1455
|
totp?: TOTPConfig;
|
|
1456
|
+
/**
|
|
1457
|
+
* Passkey/WebAuthn-specific configuration
|
|
1458
|
+
*/
|
|
188
1459
|
passkey?: PasskeyConfig;
|
|
1460
|
+
/**
|
|
1461
|
+
* Backup codes configuration
|
|
1462
|
+
* Recovery codes for when users lose access to their MFA devices
|
|
1463
|
+
*/
|
|
189
1464
|
backup?: BackupCodesConfig;
|
|
1465
|
+
/**
|
|
1466
|
+
* Adaptive MFA configuration (future: conditional MFA based on risk)
|
|
1467
|
+
* NOTE: PLACEHOLDER - Full implementation in future phase
|
|
1468
|
+
*/
|
|
190
1469
|
adaptive?: AdaptiveMFAConfig;
|
|
191
1470
|
}
|
|
1471
|
+
/**
|
|
1472
|
+
* TOTP (Time-based One-Time Password) Configuration
|
|
1473
|
+
* Used for authenticator apps like Google Authenticator, Authy, 1Password
|
|
1474
|
+
*/
|
|
192
1475
|
export interface TOTPConfig {
|
|
1476
|
+
/**
|
|
1477
|
+
* Time window for TOTP validation
|
|
1478
|
+
* Number of steps to check before/after current time
|
|
1479
|
+
* Higher values are more lenient but less secure
|
|
1480
|
+
*
|
|
1481
|
+
* @default 1 (checks current + 1 step before/after = 3 total)
|
|
1482
|
+
*/
|
|
193
1483
|
window?: number;
|
|
1484
|
+
/**
|
|
1485
|
+
* Time step in seconds
|
|
1486
|
+
* Standard TOTP uses 30 seconds
|
|
1487
|
+
*
|
|
1488
|
+
* @default 30
|
|
1489
|
+
*/
|
|
194
1490
|
stepSeconds?: number;
|
|
1491
|
+
/**
|
|
1492
|
+
* Number of digits in generated code
|
|
1493
|
+
*
|
|
1494
|
+
* @default 6
|
|
1495
|
+
*/
|
|
195
1496
|
digits?: number;
|
|
1497
|
+
/**
|
|
1498
|
+
* Hash algorithm for TOTP
|
|
1499
|
+
*
|
|
1500
|
+
* @default 'sha1' (most compatible with authenticator apps)
|
|
1501
|
+
*/
|
|
196
1502
|
algorithm?: 'sha1' | 'sha256' | 'sha512';
|
|
197
1503
|
}
|
|
1504
|
+
/**
|
|
1505
|
+
* Passkey/WebAuthn Configuration
|
|
1506
|
+
* Used for biometric authentication and hardware security keys
|
|
1507
|
+
*/
|
|
198
1508
|
export interface PasskeyConfig {
|
|
1509
|
+
/**
|
|
1510
|
+
* Relying Party name (displayed during passkey creation)
|
|
1511
|
+
* Should be your application name
|
|
1512
|
+
*
|
|
1513
|
+
* @example 'MyApp', 'Acme Corporation'
|
|
1514
|
+
*/
|
|
199
1515
|
rpName: string;
|
|
1516
|
+
/**
|
|
1517
|
+
* Relying Party ID (domain without protocol/port)
|
|
1518
|
+
* Must match the domain serving your application
|
|
1519
|
+
*
|
|
1520
|
+
* @example 'myapp.com', 'example.com'
|
|
1521
|
+
*/
|
|
200
1522
|
rpId: string;
|
|
1523
|
+
/**
|
|
1524
|
+
* Expected origin for WebAuthn operations
|
|
1525
|
+
* Must include protocol and optionally port
|
|
1526
|
+
*
|
|
1527
|
+
* @example 'https://myapp.com', 'http://localhost:3000'
|
|
1528
|
+
*/
|
|
201
1529
|
origin?: string | string[];
|
|
1530
|
+
/**
|
|
1531
|
+
* Timeout for passkey operations in milliseconds
|
|
1532
|
+
*
|
|
1533
|
+
* @default 60000 (60 seconds)
|
|
1534
|
+
*/
|
|
202
1535
|
timeout?: number;
|
|
1536
|
+
/**
|
|
1537
|
+
* Require user verification (biometric/PIN)
|
|
1538
|
+
* 'required' | 'preferred' | 'discouraged'
|
|
1539
|
+
*
|
|
1540
|
+
* @default 'preferred'
|
|
1541
|
+
*/
|
|
203
1542
|
userVerification?: 'required' | 'preferred' | 'discouraged';
|
|
1543
|
+
/**
|
|
1544
|
+
* Authenticator attachment preference
|
|
1545
|
+
* - 'platform': Built-in authenticators (Touch ID, Face ID, Windows Hello)
|
|
1546
|
+
* - 'cross-platform': Removable authenticators (USB security keys)
|
|
1547
|
+
*
|
|
1548
|
+
* @default undefined (allow both)
|
|
1549
|
+
*/
|
|
204
1550
|
authenticatorAttachment?: 'platform' | 'cross-platform';
|
|
205
1551
|
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Backup/Recovery Codes Configuration
|
|
1554
|
+
* Single-use codes for account recovery when MFA devices are unavailable
|
|
1555
|
+
*/
|
|
206
1556
|
export interface BackupCodesConfig {
|
|
1557
|
+
/**
|
|
1558
|
+
* Enable backup codes
|
|
1559
|
+
*
|
|
1560
|
+
* @default true
|
|
1561
|
+
*/
|
|
207
1562
|
enabled?: boolean;
|
|
1563
|
+
/**
|
|
1564
|
+
* Number of backup codes to generate
|
|
1565
|
+
*
|
|
1566
|
+
* @default 10
|
|
1567
|
+
*/
|
|
208
1568
|
codeCount?: number;
|
|
1569
|
+
/**
|
|
1570
|
+
* Length of each backup code (characters)
|
|
1571
|
+
*
|
|
1572
|
+
* @default 8
|
|
1573
|
+
*/
|
|
209
1574
|
codeLength?: number;
|
|
210
1575
|
}
|
|
1576
|
+
/**
|
|
1577
|
+
* Adaptive MFA Configuration
|
|
1578
|
+
*
|
|
1579
|
+
* Configures risk-based authentication that evaluates login context
|
|
1580
|
+
* (device, IP, location) against user history to determine MFA requirements.
|
|
1581
|
+
*
|
|
1582
|
+
* Risk levels are evaluated in order: low → medium → high.
|
|
1583
|
+
* Each level can have different actions (allow, require_mfa, block_signin).
|
|
1584
|
+
*
|
|
1585
|
+
* @example
|
|
1586
|
+
* ```typescript
|
|
1587
|
+
* adaptive: {
|
|
1588
|
+
* triggers: ['new_device', 'new_ip', 'new_country'],
|
|
1589
|
+
* riskLevels: {
|
|
1590
|
+
* low: { maxScore: 20, action: 'allow', notifyUser: false },
|
|
1591
|
+
* medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
|
|
1592
|
+
* high: { maxScore: 100, action: 'block_signin', notifyUser: true }
|
|
1593
|
+
* },
|
|
1594
|
+
* blockedSignIn: {
|
|
1595
|
+
* blockDuration: 60, // minutes
|
|
1596
|
+
* message: 'Sign-in blocked due to suspicious activity'
|
|
1597
|
+
* }
|
|
1598
|
+
* }
|
|
1599
|
+
* ```
|
|
1600
|
+
*/
|
|
211
1601
|
export interface AdaptiveMFAConfig {
|
|
1602
|
+
/**
|
|
1603
|
+
* Risk factors that trigger MFA requirement
|
|
1604
|
+
*
|
|
1605
|
+
* Triggers that are evaluated during authentication:
|
|
1606
|
+
* - 'new_device': First login from unknown device
|
|
1607
|
+
* - 'new_ip': Login from new IP address
|
|
1608
|
+
* - 'new_country': Login from different country
|
|
1609
|
+
* - 'impossible_travel': Geographic distance/time anomaly
|
|
1610
|
+
* - 'suspicious_activity': Unusual behavior patterns
|
|
1611
|
+
* - 'recent_password_reset': Password was reset/changed after last successful login
|
|
1612
|
+
*
|
|
1613
|
+
* @default ['new_device', 'new_ip', 'new_country']
|
|
1614
|
+
*/
|
|
212
1615
|
triggers?: Array<'new_device' | 'new_ip' | 'new_country' | 'impossible_travel' | 'suspicious_activity' | 'recent_password_reset'>;
|
|
1616
|
+
/**
|
|
1617
|
+
* Risk score threshold (0-100) to require MFA
|
|
1618
|
+
*
|
|
1619
|
+
* @default 50
|
|
1620
|
+
*/
|
|
213
1621
|
riskThreshold?: number;
|
|
1622
|
+
/**
|
|
1623
|
+
* Custom risk factor weights (overrides defaults)
|
|
1624
|
+
*
|
|
1625
|
+
* Default weights:
|
|
1626
|
+
* - new_device: 25
|
|
1627
|
+
* - new_ip: 15
|
|
1628
|
+
* - new_country: 25
|
|
1629
|
+
* - impossible_travel: 40
|
|
1630
|
+
* - suspicious_activity: 30
|
|
1631
|
+
* - incomplete_location_data: 20
|
|
1632
|
+
*
|
|
1633
|
+
* @example
|
|
1634
|
+
* ```typescript
|
|
1635
|
+
* riskWeights: {
|
|
1636
|
+
* new_device: 25,
|
|
1637
|
+
* new_country: 30,
|
|
1638
|
+
* incomplete_location_data: 25
|
|
1639
|
+
* }
|
|
1640
|
+
* ```
|
|
1641
|
+
*/
|
|
214
1642
|
riskWeights?: Record<string, number>;
|
|
1643
|
+
/**
|
|
1644
|
+
* Risk level thresholds and actions
|
|
1645
|
+
*
|
|
1646
|
+
* Defines score ranges and what action to take at each level.
|
|
1647
|
+
* Scores are evaluated in order: low → medium → high.
|
|
1648
|
+
*
|
|
1649
|
+
* @default
|
|
1650
|
+
* ```typescript
|
|
1651
|
+
* {
|
|
1652
|
+
* low: { maxScore: 20, action: 'allow', notifyUser: false },
|
|
1653
|
+
* medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
|
|
1654
|
+
* high: { maxScore: 100, action: 'require_mfa', notifyUser: true }
|
|
1655
|
+
* }
|
|
1656
|
+
* ```
|
|
1657
|
+
*
|
|
1658
|
+
* @example High-security configuration
|
|
1659
|
+
* ```typescript
|
|
1660
|
+
* riskLevels: {
|
|
1661
|
+
* low: { maxScore: 20, action: 'allow', notifyUser: false },
|
|
1662
|
+
* medium: { maxScore: 50, action: 'require_mfa', notifyUser: true },
|
|
1663
|
+
* high: { maxScore: 100, action: 'block_signin', notifyUser: true }
|
|
1664
|
+
* }
|
|
1665
|
+
* ```
|
|
1666
|
+
*/
|
|
215
1667
|
riskLevels?: {
|
|
216
1668
|
low?: RiskLevelConfig;
|
|
217
1669
|
medium?: RiskLevelConfig;
|
|
218
1670
|
high?: RiskLevelConfig;
|
|
219
1671
|
};
|
|
1672
|
+
/**
|
|
1673
|
+
* Blocked sign-in behavior
|
|
1674
|
+
*
|
|
1675
|
+
* Configuration for when high-risk sign-ins are blocked.
|
|
1676
|
+
*/
|
|
220
1677
|
blockedSignIn?: {
|
|
1678
|
+
/**
|
|
1679
|
+
* Duration (in minutes) to block user before allowing retry
|
|
1680
|
+
* If not set, block is permanent until manual review
|
|
1681
|
+
*
|
|
1682
|
+
* @default undefined (permanent until manual review)
|
|
1683
|
+
*/
|
|
221
1684
|
blockDuration?: number;
|
|
1685
|
+
/**
|
|
1686
|
+
* Custom message to show user when blocked
|
|
1687
|
+
*
|
|
1688
|
+
* @default 'Sign-in blocked due to suspicious activity. Please contact support.'
|
|
1689
|
+
*/
|
|
222
1690
|
message?: string;
|
|
1691
|
+
/**
|
|
1692
|
+
* Error code to return when blocked
|
|
1693
|
+
*
|
|
1694
|
+
* @default 'SIGNIN_BLOCKED_HIGH_RISK'
|
|
1695
|
+
*/
|
|
223
1696
|
errorCode?: string;
|
|
224
1697
|
};
|
|
1698
|
+
/**
|
|
1699
|
+
* Maximum realistic travel speed in km/h for impossible travel detection
|
|
1700
|
+
*
|
|
1701
|
+
* Used to determine if geographic distance between two locations
|
|
1702
|
+
* is impossible given the time elapsed.
|
|
1703
|
+
*
|
|
1704
|
+
* @default 900 (commercial airliner speed)
|
|
1705
|
+
*/
|
|
225
1706
|
maxTravelSpeed?: number;
|
|
1707
|
+
/**
|
|
1708
|
+
* Minimum time (hours) required between country changes when city data is missing
|
|
1709
|
+
*
|
|
1710
|
+
* Conservative threshold for detecting suspicious country changes when
|
|
1711
|
+
* MaxMind doesn't provide city-level data. If countries differ and either
|
|
1712
|
+
* city is unknown, flag as suspicious if time < threshold.
|
|
1713
|
+
*
|
|
1714
|
+
* @default 2 (2 hours minimum between country changes)
|
|
1715
|
+
*
|
|
1716
|
+
* @example
|
|
1717
|
+
* ```typescript
|
|
1718
|
+
* countryChangeThreshold: 3 // Require 3 hours minimum between country changes
|
|
1719
|
+
* ```
|
|
1720
|
+
*/
|
|
226
1721
|
countryChangeThreshold?: number;
|
|
1722
|
+
/**
|
|
1723
|
+
* Time window (hours) to check for suspicious activity
|
|
1724
|
+
*
|
|
1725
|
+
* How far back to look for suspicious audit events (failed logins,
|
|
1726
|
+
* token reuse, etc.) when evaluating risk.
|
|
1727
|
+
*
|
|
1728
|
+
* @default 1 (1 hour)
|
|
1729
|
+
*/
|
|
227
1730
|
suspiciousActivityWindow?: number;
|
|
228
1731
|
}
|
|
1732
|
+
/**
|
|
1733
|
+
* Risk level configuration
|
|
1734
|
+
*
|
|
1735
|
+
* Defines behavior for a specific risk level (low, medium, high).
|
|
1736
|
+
*
|
|
1737
|
+
* @example
|
|
1738
|
+
* ```typescript
|
|
1739
|
+
* {
|
|
1740
|
+
* maxScore: 50,
|
|
1741
|
+
* action: 'require_mfa',
|
|
1742
|
+
* notifyUser: true
|
|
1743
|
+
* }
|
|
1744
|
+
* ```
|
|
1745
|
+
*/
|
|
229
1746
|
export interface RiskLevelConfig {
|
|
1747
|
+
/**
|
|
1748
|
+
* Maximum risk score for this level (0-100)
|
|
1749
|
+
*
|
|
1750
|
+
* Scores are evaluated in order: low → medium → high.
|
|
1751
|
+
* Example: If low.maxScore = 20 and medium.maxScore = 50:
|
|
1752
|
+
* - Score 0-20: low
|
|
1753
|
+
* - Score 21-50: medium
|
|
1754
|
+
* - Score 51-100: high
|
|
1755
|
+
*/
|
|
230
1756
|
maxScore: number;
|
|
1757
|
+
/**
|
|
1758
|
+
* Action to take when risk score falls in this level
|
|
1759
|
+
*
|
|
1760
|
+
* - 'allow': Allow sign-in without MFA (normal flow)
|
|
1761
|
+
* - 'require_mfa': Require MFA verification before allowing sign-in
|
|
1762
|
+
* - 'block_signin': Block sign-in entirely (return error)
|
|
1763
|
+
*
|
|
1764
|
+
* @default 'allow' for low, 'require_mfa' for medium/high
|
|
1765
|
+
*/
|
|
231
1766
|
action?: 'allow' | 'require_mfa' | 'block_signin';
|
|
1767
|
+
/**
|
|
1768
|
+
* Whether to notify user of this risk event
|
|
1769
|
+
*
|
|
1770
|
+
* Triggers onAdaptiveMFATriggered lifecycle hook when true.
|
|
1771
|
+
*
|
|
1772
|
+
* @default false for low, true for medium/high
|
|
1773
|
+
*/
|
|
232
1774
|
notifyUser?: boolean;
|
|
233
1775
|
}
|
|
1776
|
+
/**
|
|
1777
|
+
* Adaptive MFA risk event payload
|
|
1778
|
+
*
|
|
1779
|
+
* Rich context provided to lifecycle hooks when adaptive MFA evaluates
|
|
1780
|
+
* a login attempt and detects risk factors.
|
|
1781
|
+
*
|
|
1782
|
+
* @example
|
|
1783
|
+
* ```typescript
|
|
1784
|
+
* onAdaptiveMFATriggered: async (payload) => {
|
|
1785
|
+
* console.log(`Risk score: ${payload.riskScore}`);
|
|
1786
|
+
* console.log(`Risk factors: ${payload.riskFactors.join(', ')}`);
|
|
1787
|
+
* console.log(`Action: ${payload.action}`);
|
|
1788
|
+
* }
|
|
1789
|
+
* ```
|
|
1790
|
+
*/
|
|
234
1791
|
export interface AdaptiveMFARiskEventPayload {
|
|
1792
|
+
/**
|
|
1793
|
+
* User being authenticated
|
|
1794
|
+
*/
|
|
235
1795
|
user: {
|
|
236
1796
|
sub: string;
|
|
237
1797
|
email: string;
|
|
238
1798
|
username?: string;
|
|
239
1799
|
phoneNumber?: string;
|
|
240
1800
|
};
|
|
1801
|
+
/**
|
|
1802
|
+
* Risk assessment results
|
|
1803
|
+
*/
|
|
241
1804
|
riskScore: number;
|
|
242
1805
|
riskLevel: 'low' | 'medium' | 'high';
|
|
243
1806
|
riskFactors: string[];
|
|
1807
|
+
/**
|
|
1808
|
+
* Action that will be taken
|
|
1809
|
+
*/
|
|
244
1810
|
action: 'allow' | 'require_mfa' | 'block_signin';
|
|
1811
|
+
/**
|
|
1812
|
+
* Client context (IP, device, location, etc.)
|
|
1813
|
+
*/
|
|
245
1814
|
clientInfo: {
|
|
246
1815
|
ipAddress?: string;
|
|
247
1816
|
ipCountry?: string;
|
|
@@ -253,39 +1822,244 @@ export interface AdaptiveMFARiskEventPayload {
|
|
|
253
1822
|
platform?: string;
|
|
254
1823
|
browser?: string;
|
|
255
1824
|
};
|
|
1825
|
+
/**
|
|
1826
|
+
* Authentication context
|
|
1827
|
+
*/
|
|
256
1828
|
authMethod: string;
|
|
1829
|
+
/**
|
|
1830
|
+
* Timestamp of the event
|
|
1831
|
+
*/
|
|
257
1832
|
timestamp: Date;
|
|
1833
|
+
/**
|
|
1834
|
+
* Additional metadata
|
|
1835
|
+
*/
|
|
258
1836
|
metadata?: Record<string, unknown>;
|
|
259
1837
|
}
|
|
1838
|
+
/**
|
|
1839
|
+
* Sign-in blocked event payload
|
|
1840
|
+
*
|
|
1841
|
+
* Extended payload for when a sign-in is blocked due to high risk.
|
|
1842
|
+
* Includes blocking details (duration, expiration, message).
|
|
1843
|
+
*/
|
|
260
1844
|
export interface SignInBlockedPayload extends AdaptiveMFARiskEventPayload {
|
|
1845
|
+
/**
|
|
1846
|
+
* Block duration (in minutes) if temporary, undefined if permanent
|
|
1847
|
+
*/
|
|
261
1848
|
blockDuration?: number;
|
|
1849
|
+
/**
|
|
1850
|
+
* When the block will expire (if temporary)
|
|
1851
|
+
*/
|
|
262
1852
|
blockExpiresAt?: Date;
|
|
1853
|
+
/**
|
|
1854
|
+
* Message shown to user
|
|
1855
|
+
*/
|
|
263
1856
|
message: string;
|
|
264
1857
|
}
|
|
1858
|
+
/**
|
|
1859
|
+
* Token Delivery Configuration
|
|
1860
|
+
*
|
|
1861
|
+
* Controls how JWT tokens are delivered to clients across different
|
|
1862
|
+
* transports. Defaults to 'json' to remain protocol-agnostic.
|
|
1863
|
+
*/
|
|
265
1864
|
export interface TokenDeliveryConfig {
|
|
1865
|
+
/**
|
|
1866
|
+
* Delivery method for tokens
|
|
1867
|
+
* - 'json': Response body only (default)
|
|
1868
|
+
* - 'cookies': httpOnly cookies only (browser web apps)
|
|
1869
|
+
* - 'hybrid': Cookies first (web), then Authorization header (mobile)
|
|
1870
|
+
*
|
|
1871
|
+
* @default 'json'
|
|
1872
|
+
*/
|
|
266
1873
|
method?: 'json' | 'cookies' | 'hybrid';
|
|
1874
|
+
/**
|
|
1875
|
+
* Cookie name prefix for all authentication cookies
|
|
1876
|
+
*
|
|
1877
|
+
* All cookie names are prefixed with this value to avoid conflicts with other cookies.
|
|
1878
|
+
* Default: 'nauth_'
|
|
1879
|
+
*
|
|
1880
|
+
* Cookie names generated:
|
|
1881
|
+
* - `${prefix}access_token` (default: 'nauth_access_token')
|
|
1882
|
+
* - `${prefix}refresh_token` (default: 'nauth_refresh_token')
|
|
1883
|
+
* - CSRF cookie name is also prefixed (configured via security.csrf.cookieName)
|
|
1884
|
+
*
|
|
1885
|
+
* @default 'nauth_'
|
|
1886
|
+
*
|
|
1887
|
+
* @example
|
|
1888
|
+
* ```typescript
|
|
1889
|
+
* // Custom prefix
|
|
1890
|
+
* cookieNamePrefix: 'myapp_'
|
|
1891
|
+
* // Results in: 'myapp_access_token', 'myapp_refresh_token'
|
|
1892
|
+
* ```
|
|
1893
|
+
*/
|
|
267
1894
|
cookieNamePrefix?: string;
|
|
1895
|
+
/**
|
|
1896
|
+
* Advanced cookie options (rarely needed)
|
|
1897
|
+
*
|
|
1898
|
+
* Smart defaults:
|
|
1899
|
+
* - Names: 'nauth_access_token', 'nauth_refresh_token' (prefixed by cookieNamePrefix)
|
|
1900
|
+
* - httpOnly: true (always)
|
|
1901
|
+
* - secure: true (configurable below for localhost/dev)
|
|
1902
|
+
* - sameSite: 'strict' (configurable below)
|
|
1903
|
+
* - path: '/' (configurable below)
|
|
1904
|
+
*/
|
|
268
1905
|
cookieOptions?: {
|
|
1906
|
+
/**
|
|
1907
|
+
* Use secure cookies (HTTPS only)
|
|
1908
|
+
* @default true
|
|
1909
|
+
*/
|
|
269
1910
|
secure?: boolean;
|
|
1911
|
+
/**
|
|
1912
|
+
* SameSite cookie attribute
|
|
1913
|
+
* @default 'strict'
|
|
1914
|
+
*/
|
|
270
1915
|
sameSite?: 'strict' | 'lax' | 'none';
|
|
1916
|
+
/**
|
|
1917
|
+
* Cookie path
|
|
1918
|
+
* @default '/'
|
|
1919
|
+
*/
|
|
271
1920
|
path?: string;
|
|
1921
|
+
/**
|
|
1922
|
+
* Cookie domain (for subdomain sharing)
|
|
1923
|
+
* @example '.myapp.com'
|
|
1924
|
+
*/
|
|
272
1925
|
domain?: string;
|
|
273
1926
|
};
|
|
1927
|
+
/**
|
|
1928
|
+
* Strict hybrid policy (origin-based) used when method === 'hybrid'.
|
|
1929
|
+
* webOrigins → cookies; nativeOrigins → json
|
|
1930
|
+
*/
|
|
274
1931
|
hybridPolicy?: {
|
|
275
1932
|
webOrigins?: string[];
|
|
276
1933
|
nativeOrigins?: string[];
|
|
277
1934
|
};
|
|
278
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Challenge Configuration
|
|
1938
|
+
*
|
|
1939
|
+
* Controls challenge session behavior for authentication challenges
|
|
1940
|
+
* (email verification, phone verification, MFA challenges, etc.)
|
|
1941
|
+
*/
|
|
279
1942
|
export interface ChallengeConfig {
|
|
1943
|
+
/**
|
|
1944
|
+
* Maximum allowed attempts per challenge session
|
|
1945
|
+
*
|
|
1946
|
+
* Users get this many attempts before the challenge session is invalidated.
|
|
1947
|
+
* The (maxAttempts + 1)th failure will cause "Maximum challenge attempts exceeded" error.
|
|
1948
|
+
*
|
|
1949
|
+
* @default 3
|
|
1950
|
+
*
|
|
1951
|
+
* @example
|
|
1952
|
+
* ```typescript
|
|
1953
|
+
* challenge: {
|
|
1954
|
+
* maxAttempts: 3 // User gets 3 attempts, 4th failure causes error
|
|
1955
|
+
* }
|
|
1956
|
+
* ```
|
|
1957
|
+
*/
|
|
280
1958
|
maxAttempts?: number;
|
|
281
1959
|
}
|
|
1960
|
+
/**
|
|
1961
|
+
* Geolocation configuration
|
|
1962
|
+
*
|
|
1963
|
+
* Configures IP geolocation using MaxMind GeoIP2 database files.
|
|
1964
|
+
* Platform-agnostic - works on all platforms where Node.js runs.
|
|
1965
|
+
*
|
|
1966
|
+
* @example
|
|
1967
|
+
* ```typescript
|
|
1968
|
+
* geoLocation: {
|
|
1969
|
+
* maxMind: {
|
|
1970
|
+
* licenseKey: process.env.MAXMIND_LICENSE_KEY, // Your env var name
|
|
1971
|
+
* accountId: parseInt(process.env.MAXMIND_ACCOUNT_ID || '0'),
|
|
1972
|
+
* // dbPath not set = uses system temp directory
|
|
1973
|
+
* }
|
|
1974
|
+
* }
|
|
1975
|
+
* ```
|
|
1976
|
+
*/
|
|
282
1977
|
export interface GeoLocationConfig {
|
|
1978
|
+
/**
|
|
1979
|
+
* MaxMind GeoIP2 configuration
|
|
1980
|
+
*/
|
|
283
1981
|
maxMind?: {
|
|
1982
|
+
/**
|
|
1983
|
+
* Directory path where MaxMind .mmdb files are stored or should be downloaded
|
|
1984
|
+
*
|
|
1985
|
+
* **Usage Modes:**
|
|
1986
|
+
* 1. **Auto-download mode**: Point to directory, toolkit downloads files
|
|
1987
|
+
* 2. **External management mode**: Point to directory with existing files, toolkit uses them
|
|
1988
|
+
* 3. **Default**: System temp directory (ephemeral, cleared on reboot)
|
|
1989
|
+
*
|
|
1990
|
+
* **Examples:**
|
|
1991
|
+
*
|
|
1992
|
+
* Auto-download to custom path:
|
|
1993
|
+
* ```typescript
|
|
1994
|
+
* maxMind: {
|
|
1995
|
+
* dbPath: '/app/data/maxmind',
|
|
1996
|
+
* licenseKey: '...',
|
|
1997
|
+
* accountId: 123,
|
|
1998
|
+
* autoDownloadOnStartup: true
|
|
1999
|
+
* }
|
|
2000
|
+
* ```
|
|
2001
|
+
*
|
|
2002
|
+
* Use existing files (consumer manages downloads):
|
|
2003
|
+
* ```typescript
|
|
2004
|
+
* maxMind: {
|
|
2005
|
+
* dbPath: '/app/data/maxmind',
|
|
2006
|
+
* // No licenseKey/accountId needed - toolkit just loads existing files
|
|
2007
|
+
* skipDownloads: true // Disable all download functionality
|
|
2008
|
+
* }
|
|
2009
|
+
* ```
|
|
2010
|
+
*
|
|
2011
|
+
* Default temp directory (auto-download):
|
|
2012
|
+
* ```typescript
|
|
2013
|
+
* maxMind: {
|
|
2014
|
+
* licenseKey: '...',
|
|
2015
|
+
* accountId: 123
|
|
2016
|
+
* // dbPath defaults to os.tmpdir() + '/nauth_maxmind'
|
|
2017
|
+
* }
|
|
2018
|
+
* ```
|
|
2019
|
+
*
|
|
2020
|
+
* Works on all platforms (Mac, Linux, Windows, Docker, serverless).
|
|
2021
|
+
*/
|
|
284
2022
|
dbPath?: string;
|
|
2023
|
+
/**
|
|
2024
|
+
* Skip all database downloads (consumer manages updates externally)
|
|
2025
|
+
*
|
|
2026
|
+
* If true, toolkit will only load existing .mmdb files from dbPath.
|
|
2027
|
+
* Useful when:
|
|
2028
|
+
* - Using MaxMind's geoipupdate tool
|
|
2029
|
+
* - Managing downloads via external cron jobs
|
|
2030
|
+
* - Databases are pre-installed in containers
|
|
2031
|
+
* - Databases come from shared volumes/NFS
|
|
2032
|
+
*
|
|
2033
|
+
* When true, licenseKey and accountId are not required.
|
|
2034
|
+
* Service will log a warning if no database files are found.
|
|
2035
|
+
*
|
|
2036
|
+
* @default false
|
|
2037
|
+
*/
|
|
285
2038
|
skipDownloads?: boolean;
|
|
2039
|
+
/**
|
|
2040
|
+
* MaxMind license key (required for downloading databases, not needed if skipDownloads is true)
|
|
2041
|
+
*/
|
|
286
2042
|
licenseKey?: string;
|
|
2043
|
+
/**
|
|
2044
|
+
* MaxMind account ID (required for downloading databases, not needed if skipDownloads is true)
|
|
2045
|
+
*/
|
|
287
2046
|
accountId?: number;
|
|
2047
|
+
/**
|
|
2048
|
+
* Auto-download on startup if files don't exist
|
|
2049
|
+
* Default: false
|
|
2050
|
+
*
|
|
2051
|
+
* WARNING: Only enable if using distributed storage adapter (Redis/Database)
|
|
2052
|
+
* to prevent concurrent downloads in multi-server deployments.
|
|
2053
|
+
*
|
|
2054
|
+
* Ignored if skipDownloads is true.
|
|
2055
|
+
*/
|
|
288
2056
|
autoDownloadOnStartup?: boolean;
|
|
2057
|
+
/**
|
|
2058
|
+
* Edition IDs to download
|
|
2059
|
+
* Default: ['GeoLite2-City', 'GeoLite2-Country']
|
|
2060
|
+
*
|
|
2061
|
+
* Ignored if skipDownloads is true.
|
|
2062
|
+
*/
|
|
289
2063
|
editions?: string[];
|
|
290
2064
|
};
|
|
291
2065
|
}
|