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