@nauth-toolkit/core 0.1.0
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 +10 -0
- package/dist/adapters/database-columns.d.ts.map +1 -0
- package/dist/adapters/database-columns.js +85 -0
- package/dist/adapters/database-columns.js.map +1 -0
- package/dist/adapters/express.adapter.d.ts +41 -0
- package/dist/adapters/express.adapter.d.ts.map +1 -0
- package/dist/adapters/express.adapter.js +188 -0
- package/dist/adapters/express.adapter.js.map +1 -0
- package/dist/adapters/fastify.adapter.d.ts +33 -0
- package/dist/adapters/fastify.adapter.d.ts.map +1 -0
- package/dist/adapters/fastify.adapter.js +223 -0
- package/dist/adapters/fastify.adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +5 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +25 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/storage.factory.d.ts +7 -0
- package/dist/adapters/storage.factory.d.ts.map +1 -0
- package/dist/adapters/storage.factory.js +24 -0
- package/dist/adapters/storage.factory.js.map +1 -0
- package/dist/bootstrap.d.ts +41 -0
- package/dist/bootstrap.d.ts.map +1 -0
- package/dist/bootstrap.js +113 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/dto/auth-challenge.dto.d.ts +19 -0
- package/dist/dto/auth-challenge.dto.d.ts.map +1 -0
- package/dist/dto/auth-challenge.dto.js +86 -0
- package/dist/dto/auth-challenge.dto.js.map +1 -0
- package/dist/dto/auth-response.dto.d.ts +31 -0
- package/dist/dto/auth-response.dto.d.ts.map +1 -0
- package/dist/dto/auth-response.dto.js +18 -0
- package/dist/dto/auth-response.dto.js.map +1 -0
- package/dist/dto/challenge-response.dto.d.ts +36 -0
- package/dist/dto/challenge-response.dto.d.ts.map +1 -0
- package/dist/dto/challenge-response.dto.js +3 -0
- package/dist/dto/challenge-response.dto.js.map +1 -0
- package/dist/dto/change-password-request.dto.d.ts +5 -0
- package/dist/dto/change-password-request.dto.d.ts.map +1 -0
- package/dist/dto/change-password-request.dto.js +30 -0
- package/dist/dto/change-password-request.dto.js.map +1 -0
- package/dist/dto/change-password-response.dto.d.ts +4 -0
- package/dist/dto/change-password-response.dto.d.ts.map +1 -0
- package/dist/dto/change-password-response.dto.js +8 -0
- package/dist/dto/change-password-response.dto.js.map +1 -0
- package/dist/dto/change-password.dto.d.ts +5 -0
- package/dist/dto/change-password.dto.d.ts.map +1 -0
- package/dist/dto/change-password.dto.js +29 -0
- package/dist/dto/change-password.dto.js.map +1 -0
- package/dist/dto/error-response.dto.d.ts +9 -0
- package/dist/dto/error-response.dto.d.ts.map +1 -0
- package/dist/dto/error-response.dto.js +59 -0
- package/dist/dto/error-response.dto.js.map +1 -0
- package/dist/dto/get-available-methods.dto.d.ts +7 -0
- package/dist/dto/get-available-methods.dto.d.ts.map +1 -0
- package/dist/dto/get-available-methods.dto.js +33 -0
- package/dist/dto/get-available-methods.dto.js.map +1 -0
- package/dist/dto/get-challenge-data-response.dto.d.ts +4 -0
- package/dist/dto/get-challenge-data-response.dto.d.ts.map +1 -0
- package/dist/dto/get-challenge-data-response.dto.js +8 -0
- package/dist/dto/get-challenge-data-response.dto.js.map +1 -0
- package/dist/dto/get-challenge-data.dto.d.ts +8 -0
- package/dist/dto/get-challenge-data.dto.d.ts.map +1 -0
- package/dist/dto/get-challenge-data.dto.js +40 -0
- package/dist/dto/get-challenge-data.dto.js.map +1 -0
- package/dist/dto/get-client-info.dto.d.ts +17 -0
- package/dist/dto/get-client-info.dto.d.ts.map +1 -0
- package/dist/dto/get-client-info.dto.js +20 -0
- package/dist/dto/get-client-info.dto.js.map +1 -0
- package/dist/dto/get-device-token-response.dto.d.ts +4 -0
- package/dist/dto/get-device-token-response.dto.d.ts.map +1 -0
- package/dist/dto/get-device-token-response.dto.js +8 -0
- package/dist/dto/get-device-token-response.dto.js.map +1 -0
- package/dist/dto/get-events-by-type.dto.d.ts +17 -0
- package/dist/dto/get-events-by-type.dto.d.ts.map +1 -0
- package/dist/dto/get-events-by-type.dto.js +20 -0
- package/dist/dto/get-events-by-type.dto.js.map +1 -0
- package/dist/dto/get-ip-address-response.dto.d.ts +4 -0
- package/dist/dto/get-ip-address-response.dto.d.ts.map +1 -0
- package/dist/dto/get-ip-address-response.dto.js +8 -0
- package/dist/dto/get-ip-address-response.dto.js.map +1 -0
- package/dist/dto/get-mfa-status.dto.d.ts +16 -0
- package/dist/dto/get-mfa-status.dto.d.ts.map +1 -0
- package/dist/dto/get-mfa-status.dto.js +41 -0
- package/dist/dto/get-mfa-status.dto.js.map +1 -0
- package/dist/dto/get-risk-assessment-history.dto.d.ts +9 -0
- package/dist/dto/get-risk-assessment-history.dto.d.ts.map +1 -0
- package/dist/dto/get-risk-assessment-history.dto.js +13 -0
- package/dist/dto/get-risk-assessment-history.dto.js.map +1 -0
- package/dist/dto/get-session-id-response.dto.d.ts +4 -0
- package/dist/dto/get-session-id-response.dto.d.ts.map +1 -0
- package/dist/dto/get-session-id-response.dto.js +8 -0
- package/dist/dto/get-session-id-response.dto.js.map +1 -0
- package/dist/dto/get-setup-data-response.dto.d.ts +4 -0
- package/dist/dto/get-setup-data-response.dto.d.ts.map +1 -0
- package/dist/dto/get-setup-data-response.dto.js +8 -0
- package/dist/dto/get-setup-data-response.dto.js.map +1 -0
- package/dist/dto/get-setup-data.dto.d.ts +7 -0
- package/dist/dto/get-setup-data.dto.d.ts.map +1 -0
- package/dist/dto/get-setup-data.dto.js +43 -0
- package/dist/dto/get-setup-data.dto.js.map +1 -0
- package/dist/dto/get-suspicious-activity.dto.d.ts +9 -0
- package/dist/dto/get-suspicious-activity.dto.d.ts.map +1 -0
- package/dist/dto/get-suspicious-activity.dto.js +13 -0
- package/dist/dto/get-suspicious-activity.dto.js.map +1 -0
- package/dist/dto/get-user-agent-response.dto.d.ts +4 -0
- package/dist/dto/get-user-agent-response.dto.d.ts.map +1 -0
- package/dist/dto/get-user-agent-response.dto.js +8 -0
- package/dist/dto/get-user-agent-response.dto.js.map +1 -0
- package/dist/dto/get-user-auth-history.dto.d.ts +20 -0
- package/dist/dto/get-user-auth-history.dto.d.ts.map +1 -0
- package/dist/dto/get-user-auth-history.dto.js +22 -0
- package/dist/dto/get-user-auth-history.dto.js.map +1 -0
- package/dist/dto/get-user-by-email.dto.d.ts +5 -0
- package/dist/dto/get-user-by-email.dto.d.ts.map +1 -0
- package/dist/dto/get-user-by-email.dto.js +36 -0
- package/dist/dto/get-user-by-email.dto.js.map +1 -0
- package/dist/dto/get-user-by-id.dto.d.ts +4 -0
- package/dist/dto/get-user-by-id.dto.d.ts.map +1 -0
- package/dist/dto/get-user-by-id.dto.js +29 -0
- package/dist/dto/get-user-by-id.dto.js.map +1 -0
- package/dist/dto/get-user-devices.dto.d.ts +8 -0
- package/dist/dto/get-user-devices.dto.d.ts.map +1 -0
- package/dist/dto/get-user-devices.dto.js +33 -0
- package/dist/dto/get-user-devices.dto.js.map +1 -0
- package/dist/dto/get-user-response.dto.d.ts +2 -0
- package/dist/dto/get-user-response.dto.d.ts.map +1 -0
- package/dist/dto/get-user-response.dto.js +6 -0
- package/dist/dto/get-user-response.dto.js.map +1 -0
- package/dist/dto/has-provider.dto.d.ts +7 -0
- package/dist/dto/has-provider.dto.d.ts.map +1 -0
- package/dist/dto/has-provider.dto.js +38 -0
- package/dist/dto/has-provider.dto.js.map +1 -0
- package/dist/dto/index.d.ts +51 -0
- package/dist/dto/index.d.ts.map +1 -0
- package/dist/dto/index.js +67 -0
- package/dist/dto/index.js.map +1 -0
- package/dist/dto/is-trusted-device-response.dto.d.ts +4 -0
- package/dist/dto/is-trusted-device-response.dto.d.ts.map +1 -0
- package/dist/dto/is-trusted-device-response.dto.js +8 -0
- package/dist/dto/is-trusted-device-response.dto.js.map +1 -0
- package/dist/dto/list-providers-response.dto.d.ts +4 -0
- package/dist/dto/list-providers-response.dto.d.ts.map +1 -0
- package/dist/dto/list-providers-response.dto.js +8 -0
- package/dist/dto/list-providers-response.dto.js.map +1 -0
- package/dist/dto/login.dto.d.ts +7 -0
- package/dist/dto/login.dto.d.ts.map +1 -0
- package/dist/dto/login.dto.js +68 -0
- package/dist/dto/login.dto.js.map +1 -0
- package/dist/dto/logout-all-response.dto.d.ts +4 -0
- package/dist/dto/logout-all-response.dto.d.ts.map +1 -0
- package/dist/dto/logout-all-response.dto.js +8 -0
- package/dist/dto/logout-all-response.dto.js.map +1 -0
- package/dist/dto/logout-all.dto.d.ts +5 -0
- package/dist/dto/logout-all.dto.d.ts.map +1 -0
- package/dist/dto/logout-all.dto.js +42 -0
- package/dist/dto/logout-all.dto.js.map +1 -0
- package/dist/dto/logout-response.dto.d.ts +4 -0
- package/dist/dto/logout-response.dto.d.ts.map +1 -0
- package/dist/dto/logout-response.dto.js +8 -0
- package/dist/dto/logout-response.dto.js.map +1 -0
- package/dist/dto/logout.dto.d.ts +5 -0
- package/dist/dto/logout.dto.d.ts.map +1 -0
- package/dist/dto/logout.dto.js +36 -0
- package/dist/dto/logout.dto.js.map +1 -0
- package/dist/dto/refresh-token.dto.d.ts +4 -0
- package/dist/dto/refresh-token.dto.d.ts.map +1 -0
- package/dist/dto/refresh-token.dto.js +24 -0
- package/dist/dto/refresh-token.dto.js.map +1 -0
- package/dist/dto/remove-devices.dto.d.ts +9 -0
- package/dist/dto/remove-devices.dto.d.ts.map +1 -0
- package/dist/dto/remove-devices.dto.js +50 -0
- package/dist/dto/remove-devices.dto.js.map +1 -0
- package/dist/dto/resend-code-response.dto.d.ts +4 -0
- package/dist/dto/resend-code-response.dto.d.ts.map +1 -0
- package/dist/dto/resend-code-response.dto.js +8 -0
- package/dist/dto/resend-code-response.dto.js.map +1 -0
- package/dist/dto/resend-code.dto.d.ts +4 -0
- package/dist/dto/resend-code.dto.d.ts.map +1 -0
- package/dist/dto/resend-code.dto.js +29 -0
- package/dist/dto/resend-code.dto.js.map +1 -0
- package/dist/dto/reset-password.dto.d.ts +8 -0
- package/dist/dto/reset-password.dto.d.ts.map +1 -0
- package/dist/dto/reset-password.dto.js +61 -0
- package/dist/dto/reset-password.dto.js.map +1 -0
- package/dist/dto/respond-challenge.dto.d.ts +33 -0
- package/dist/dto/respond-challenge.dto.d.ts.map +1 -0
- package/dist/dto/respond-challenge.dto.js +131 -0
- package/dist/dto/respond-challenge.dto.js.map +1 -0
- package/dist/dto/set-mfa-exemption.dto.d.ts +12 -0
- package/dist/dto/set-mfa-exemption.dto.d.ts.map +1 -0
- package/dist/dto/set-mfa-exemption.dto.js +66 -0
- package/dist/dto/set-mfa-exemption.dto.js.map +1 -0
- package/dist/dto/set-must-change-password-response.dto.d.ts +4 -0
- package/dist/dto/set-must-change-password-response.dto.d.ts.map +1 -0
- package/dist/dto/set-must-change-password-response.dto.js +8 -0
- package/dist/dto/set-must-change-password-response.dto.js.map +1 -0
- package/dist/dto/set-must-change-password.dto.d.ts +4 -0
- package/dist/dto/set-must-change-password.dto.d.ts.map +1 -0
- package/dist/dto/set-must-change-password.dto.js +29 -0
- package/dist/dto/set-must-change-password.dto.js.map +1 -0
- package/dist/dto/set-preferred-method.dto.d.ts +8 -0
- package/dist/dto/set-preferred-method.dto.d.ts.map +1 -0
- package/dist/dto/set-preferred-method.dto.js +49 -0
- package/dist/dto/set-preferred-method.dto.js.map +1 -0
- package/dist/dto/setup-mfa.dto.d.ts +9 -0
- package/dist/dto/setup-mfa.dto.d.ts.map +1 -0
- package/dist/dto/setup-mfa.dto.js +55 -0
- package/dist/dto/setup-mfa.dto.js.map +1 -0
- package/dist/dto/signup.dto.d.ts +10 -0
- package/dist/dto/signup.dto.d.ts.map +1 -0
- package/dist/dto/signup.dto.js +109 -0
- package/dist/dto/signup.dto.js.map +1 -0
- package/dist/dto/social-auth.dto.d.ts +54 -0
- package/dist/dto/social-auth.dto.d.ts.map +1 -0
- package/dist/dto/social-auth.dto.js +232 -0
- package/dist/dto/social-auth.dto.js.map +1 -0
- package/dist/dto/trust-device-response.dto.d.ts +4 -0
- package/dist/dto/trust-device-response.dto.d.ts.map +1 -0
- package/dist/dto/trust-device-response.dto.js +8 -0
- package/dist/dto/trust-device-response.dto.js.map +1 -0
- package/dist/dto/trust-device.dto.d.ts +1 -0
- package/dist/dto/trust-device.dto.d.ts.map +1 -0
- package/dist/dto/trust-device.dto.js +2 -0
- package/dist/dto/trust-device.dto.js.map +1 -0
- package/dist/dto/update-user-attributes-request.dto.d.ts +5 -0
- package/dist/dto/update-user-attributes-request.dto.d.ts.map +1 -0
- package/dist/dto/update-user-attributes-request.dto.js +30 -0
- package/dist/dto/update-user-attributes-request.dto.js.map +1 -0
- package/dist/dto/user-response.dto.d.ts +20 -0
- package/dist/dto/user-response.dto.d.ts.map +1 -0
- package/dist/dto/user-response.dto.js +42 -0
- package/dist/dto/user-response.dto.js.map +1 -0
- package/dist/dto/user-update.dto.d.ts +12 -0
- package/dist/dto/user-update.dto.d.ts.map +1 -0
- package/dist/dto/user-update.dto.js +119 -0
- package/dist/dto/user-update.dto.js.map +1 -0
- package/dist/dto/verify-email.dto.d.ts +29 -0
- package/dist/dto/verify-email.dto.d.ts.map +1 -0
- package/dist/dto/verify-email.dto.js +161 -0
- package/dist/dto/verify-email.dto.js.map +1 -0
- package/dist/dto/verify-mfa-code.dto.d.ts +10 -0
- package/dist/dto/verify-mfa-code.dto.d.ts.map +1 -0
- package/dist/dto/verify-mfa-code.dto.js +56 -0
- package/dist/dto/verify-mfa-code.dto.js.map +1 -0
- package/dist/dto/verify-phone-by-sub.dto.d.ts +6 -0
- package/dist/dto/verify-phone-by-sub.dto.d.ts.map +1 -0
- package/dist/dto/verify-phone-by-sub.dto.js +49 -0
- package/dist/dto/verify-phone-by-sub.dto.js.map +1 -0
- package/dist/dto/verify-phone.dto.d.ts +24 -0
- package/dist/dto/verify-phone.dto.d.ts.map +1 -0
- package/dist/dto/verify-phone.dto.js +124 -0
- package/dist/dto/verify-phone.dto.js.map +1 -0
- package/dist/entities/auth-audit.entity.d.ts +31 -0
- package/dist/entities/auth-audit.entity.d.ts.map +1 -0
- package/dist/entities/auth-audit.entity.js +33 -0
- package/dist/entities/auth-audit.entity.js.map +1 -0
- package/dist/entities/challenge-session.entity.d.ts +17 -0
- package/dist/entities/challenge-session.entity.d.ts.map +1 -0
- package/dist/entities/challenge-session.entity.js +21 -0
- package/dist/entities/challenge-session.entity.js.map +1 -0
- package/dist/entities/index.d.ts +12 -0
- package/dist/entities/index.d.ts.map +1 -0
- package/dist/entities/index.js +26 -0
- package/dist/entities/index.js.map +1 -0
- package/dist/entities/login-attempt.entity.d.ts +13 -0
- package/dist/entities/login-attempt.entity.d.ts.map +1 -0
- package/dist/entities/login-attempt.entity.js +17 -0
- package/dist/entities/login-attempt.entity.js.map +1 -0
- package/dist/entities/mfa-device.entity.d.ts +22 -0
- package/dist/entities/mfa-device.entity.d.ts.map +1 -0
- package/dist/entities/mfa-device.entity.js +25 -0
- package/dist/entities/mfa-device.entity.js.map +1 -0
- package/dist/entities/rate-limit.entity.d.ts +9 -0
- package/dist/entities/rate-limit.entity.d.ts.map +1 -0
- package/dist/entities/rate-limit.entity.js +13 -0
- package/dist/entities/rate-limit.entity.js.map +1 -0
- package/dist/entities/session.entity.d.ts +32 -0
- package/dist/entities/session.entity.d.ts.map +1 -0
- package/dist/entities/session.entity.js +36 -0
- package/dist/entities/session.entity.js.map +1 -0
- package/dist/entities/social-account.entity.d.ts +13 -0
- package/dist/entities/social-account.entity.d.ts.map +1 -0
- package/dist/entities/social-account.entity.js +17 -0
- package/dist/entities/social-account.entity.js.map +1 -0
- package/dist/entities/storage-lock.entity.d.ts +8 -0
- package/dist/entities/storage-lock.entity.d.ts.map +1 -0
- package/dist/entities/storage-lock.entity.js +12 -0
- package/dist/entities/storage-lock.entity.js.map +1 -0
- package/dist/entities/trusted-device.entity.d.ts +17 -0
- package/dist/entities/trusted-device.entity.d.ts.map +1 -0
- package/dist/entities/trusted-device.entity.js +21 -0
- package/dist/entities/trusted-device.entity.js.map +1 -0
- package/dist/entities/user.entity.d.ts +41 -0
- package/dist/entities/user.entity.d.ts.map +1 -0
- package/dist/entities/user.entity.js +45 -0
- package/dist/entities/user.entity.js.map +1 -0
- package/dist/entities/verification-token.entity.d.ts +19 -0
- package/dist/entities/verification-token.entity.d.ts.map +1 -0
- package/dist/entities/verification-token.entity.js +29 -0
- package/dist/entities/verification-token.entity.js.map +1 -0
- package/dist/enums/auth-audit-event-type.enum.d.ts +55 -0
- package/dist/enums/auth-audit-event-type.enum.d.ts.map +1 -0
- package/dist/enums/auth-audit-event-type.enum.js +59 -0
- package/dist/enums/auth-audit-event-type.enum.js.map +1 -0
- package/dist/enums/error-codes.enum.d.ts +53 -0
- package/dist/enums/error-codes.enum.d.ts.map +1 -0
- package/dist/enums/error-codes.enum.js +57 -0
- package/dist/enums/error-codes.enum.js.map +1 -0
- package/dist/enums/mfa-method.enum.d.ts +11 -0
- package/dist/enums/mfa-method.enum.d.ts.map +1 -0
- package/dist/enums/mfa-method.enum.js +18 -0
- package/dist/enums/mfa-method.enum.js.map +1 -0
- package/dist/enums/risk-factor.enum.d.ts +14 -0
- package/dist/enums/risk-factor.enum.d.ts.map +1 -0
- package/dist/enums/risk-factor.enum.js +18 -0
- package/dist/enums/risk-factor.enum.js.map +1 -0
- package/dist/exceptions/nauth.exception.d.ts +18 -0
- package/dist/exceptions/nauth.exception.d.ts.map +1 -0
- package/dist/exceptions/nauth.exception.js +64 -0
- package/dist/exceptions/nauth.exception.js.map +1 -0
- package/dist/handlers/auth.handler.d.ts +18 -0
- package/dist/handlers/auth.handler.d.ts.map +1 -0
- package/dist/handlers/auth.handler.js +173 -0
- package/dist/handlers/auth.handler.js.map +1 -0
- package/dist/handlers/client-info.handler.d.ts +12 -0
- package/dist/handlers/client-info.handler.d.ts.map +1 -0
- package/dist/handlers/client-info.handler.js +61 -0
- package/dist/handlers/client-info.handler.js.map +1 -0
- package/dist/handlers/csrf.handler.d.ts +13 -0
- package/dist/handlers/csrf.handler.d.ts.map +1 -0
- package/dist/handlers/csrf.handler.js +84 -0
- package/dist/handlers/csrf.handler.js.map +1 -0
- package/dist/handlers/token-delivery.handler.d.ts +12 -0
- package/dist/handlers/token-delivery.handler.d.ts.map +1 -0
- package/dist/handlers/token-delivery.handler.js +86 -0
- package/dist/handlers/token-delivery.handler.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/client-info.interface.d.ts +16 -0
- package/dist/interfaces/client-info.interface.d.ts.map +1 -0
- package/dist/interfaces/client-info.interface.js +3 -0
- package/dist/interfaces/client-info.interface.js.map +1 -0
- package/dist/interfaces/config.interface.d.ts +279 -0
- package/dist/interfaces/config.interface.d.ts.map +1 -0
- package/dist/interfaces/config.interface.js +3 -0
- package/dist/interfaces/config.interface.js.map +1 -0
- package/dist/interfaces/entities.interface.d.ts +169 -0
- package/dist/interfaces/entities.interface.d.ts.map +1 -0
- package/dist/interfaces/entities.interface.js +3 -0
- package/dist/interfaces/entities.interface.js.map +1 -0
- package/dist/interfaces/index.d.ts +11 -0
- package/dist/interfaces/index.d.ts.map +1 -0
- package/dist/interfaces/index.js +27 -0
- package/dist/interfaces/index.js.map +1 -0
- package/dist/interfaces/logger.interface.d.ts +43 -0
- package/dist/interfaces/logger.interface.d.ts.map +1 -0
- package/dist/interfaces/logger.interface.js +12 -0
- package/dist/interfaces/logger.interface.js.map +1 -0
- package/dist/interfaces/mfa-provider.interface.d.ts +12 -0
- package/dist/interfaces/mfa-provider.interface.d.ts.map +1 -0
- package/dist/interfaces/mfa-provider.interface.js +3 -0
- package/dist/interfaces/mfa-provider.interface.js.map +1 -0
- package/dist/interfaces/oauth.interface.d.ts +24 -0
- package/dist/interfaces/oauth.interface.d.ts.map +1 -0
- package/dist/interfaces/oauth.interface.js +3 -0
- package/dist/interfaces/oauth.interface.js.map +1 -0
- package/dist/interfaces/provider.interface.d.ts +12 -0
- package/dist/interfaces/provider.interface.d.ts.map +1 -0
- package/dist/interfaces/provider.interface.js +3 -0
- package/dist/interfaces/provider.interface.js.map +1 -0
- package/dist/interfaces/social-auth-provider.interface.d.ts +13 -0
- package/dist/interfaces/social-auth-provider.interface.d.ts.map +1 -0
- package/dist/interfaces/social-auth-provider.interface.js +3 -0
- package/dist/interfaces/social-auth-provider.interface.js.map +1 -0
- package/dist/interfaces/storage-adapter.interface.d.ts +39 -0
- package/dist/interfaces/storage-adapter.interface.d.ts.map +1 -0
- package/dist/interfaces/storage-adapter.interface.js +3 -0
- package/dist/interfaces/storage-adapter.interface.js.map +1 -0
- package/dist/interfaces/template.interface.d.ts +99 -0
- package/dist/interfaces/template.interface.d.ts.map +1 -0
- package/dist/interfaces/template.interface.js +15 -0
- package/dist/interfaces/template.interface.js.map +1 -0
- package/dist/interfaces/token-verifier.interface.d.ts +7 -0
- package/dist/interfaces/token-verifier.interface.d.ts.map +1 -0
- package/dist/interfaces/token-verifier.interface.js +3 -0
- package/dist/interfaces/token-verifier.interface.js.map +1 -0
- package/dist/internal.d.ts +20 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +53 -0
- package/dist/internal.js.map +1 -0
- package/dist/platform/interfaces.d.ts +56 -0
- package/dist/platform/interfaces.d.ts.map +1 -0
- package/dist/platform/interfaces.js +3 -0
- package/dist/platform/interfaces.js.map +1 -0
- package/dist/schemas/auth-config.schema.d.ts +3411 -0
- package/dist/schemas/auth-config.schema.d.ts.map +1 -0
- package/dist/schemas/auth-config.schema.js +428 -0
- package/dist/schemas/auth-config.schema.js.map +1 -0
- package/dist/services/adaptive-mfa-decision.service.d.ts +39 -0
- package/dist/services/adaptive-mfa-decision.service.d.ts.map +1 -0
- package/dist/services/adaptive-mfa-decision.service.js +223 -0
- package/dist/services/adaptive-mfa-decision.service.js.map +1 -0
- package/dist/services/auth-audit.service.d.ts +44 -0
- package/dist/services/auth-audit.service.d.ts.map +1 -0
- package/dist/services/auth-audit.service.js +241 -0
- package/dist/services/auth-audit.service.js.map +1 -0
- package/dist/services/auth-challenge-helper.service.d.ts +48 -0
- package/dist/services/auth-challenge-helper.service.d.ts.map +1 -0
- package/dist/services/auth-challenge-helper.service.js +425 -0
- package/dist/services/auth-challenge-helper.service.js.map +1 -0
- package/dist/services/auth-flow-context-builder.service.d.ts +31 -0
- package/dist/services/auth-flow-context-builder.service.d.ts.map +1 -0
- package/dist/services/auth-flow-context-builder.service.js +253 -0
- package/dist/services/auth-flow-context-builder.service.js.map +1 -0
- package/dist/services/auth-flow-rules.d.ts +18 -0
- package/dist/services/auth-flow-rules.d.ts.map +1 -0
- package/dist/services/auth-flow-rules.js +55 -0
- package/dist/services/auth-flow-rules.js.map +1 -0
- package/dist/services/auth-flow-state-definitions.d.ts +5 -0
- package/dist/services/auth-flow-state-definitions.d.ts.map +1 -0
- package/dist/services/auth-flow-state-definitions.js +87 -0
- package/dist/services/auth-flow-state-definitions.js.map +1 -0
- package/dist/services/auth-flow-state-machine.service.d.ts +17 -0
- package/dist/services/auth-flow-state-machine.service.d.ts.map +1 -0
- package/dist/services/auth-flow-state-machine.service.js +91 -0
- package/dist/services/auth-flow-state-machine.service.js.map +1 -0
- package/dist/services/auth-flow-state-machine.types.d.ts +55 -0
- package/dist/services/auth-flow-state-machine.types.d.ts.map +1 -0
- package/dist/services/auth-flow-state-machine.types.js +16 -0
- package/dist/services/auth-flow-state-machine.types.js.map +1 -0
- package/dist/services/auth.service.d.ts +87 -0
- package/dist/services/auth.service.d.ts.map +1 -0
- package/dist/services/auth.service.js +2356 -0
- package/dist/services/auth.service.js.map +1 -0
- package/dist/services/challenge.service.d.ts +32 -0
- package/dist/services/challenge.service.d.ts.map +1 -0
- package/dist/services/challenge.service.js +293 -0
- package/dist/services/challenge.service.js.map +1 -0
- package/dist/services/client-info.service.d.ts +20 -0
- package/dist/services/client-info.service.d.ts.map +1 -0
- package/dist/services/client-info.service.js +202 -0
- package/dist/services/client-info.service.js.map +1 -0
- package/dist/services/csrf.service.d.ts +13 -0
- package/dist/services/csrf.service.d.ts.map +1 -0
- package/dist/services/csrf.service.js +67 -0
- package/dist/services/csrf.service.js.map +1 -0
- package/dist/services/email-verification.service.d.ts +30 -0
- package/dist/services/email-verification.service.d.ts.map +1 -0
- package/dist/services/email-verification.service.js +373 -0
- package/dist/services/email-verification.service.js.map +1 -0
- package/dist/services/geo-location.service.d.ts +85 -0
- package/dist/services/geo-location.service.d.ts.map +1 -0
- package/dist/services/geo-location.service.js +338 -0
- package/dist/services/geo-location.service.js.map +1 -0
- package/dist/services/index.d.ts +14 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +30 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/jwt.service.d.ts +62 -0
- package/dist/services/jwt.service.d.ts.map +1 -0
- package/dist/services/jwt.service.js +261 -0
- package/dist/services/jwt.service.js.map +1 -0
- package/dist/services/mfa-base.service.d.ts +37 -0
- package/dist/services/mfa-base.service.d.ts.map +1 -0
- package/dist/services/mfa-base.service.js +297 -0
- package/dist/services/mfa-base.service.js.map +1 -0
- package/dist/services/mfa.service.d.ts +35 -0
- package/dist/services/mfa.service.d.ts.map +1 -0
- package/dist/services/mfa.service.js +449 -0
- package/dist/services/mfa.service.js.map +1 -0
- package/dist/services/password.service.d.ts +19 -0
- package/dist/services/password.service.d.ts.map +1 -0
- package/dist/services/password.service.js +150 -0
- package/dist/services/password.service.js.map +1 -0
- package/dist/services/phone-verification.service.d.ts +32 -0
- package/dist/services/phone-verification.service.d.ts.map +1 -0
- package/dist/services/phone-verification.service.js +474 -0
- package/dist/services/phone-verification.service.js.map +1 -0
- package/dist/services/risk-detection.service.d.ts +30 -0
- package/dist/services/risk-detection.service.d.ts.map +1 -0
- package/dist/services/risk-detection.service.js +518 -0
- package/dist/services/risk-detection.service.js.map +1 -0
- package/dist/services/risk-scoring.service.d.ts +12 -0
- package/dist/services/risk-scoring.service.d.ts.map +1 -0
- package/dist/services/risk-scoring.service.js +44 -0
- package/dist/services/risk-scoring.service.js.map +1 -0
- package/dist/services/session.service.d.ts +64 -0
- package/dist/services/session.service.d.ts.map +1 -0
- package/dist/services/session.service.js +455 -0
- package/dist/services/session.service.js.map +1 -0
- package/dist/services/social-auth-base.service.d.ts +57 -0
- package/dist/services/social-auth-base.service.d.ts.map +1 -0
- package/dist/services/social-auth-base.service.js +340 -0
- package/dist/services/social-auth-base.service.js.map +1 -0
- package/dist/services/social-auth.service.d.ts +31 -0
- package/dist/services/social-auth.service.d.ts.map +1 -0
- package/dist/services/social-auth.service.js +172 -0
- package/dist/services/social-auth.service.js.map +1 -0
- package/dist/services/social-provider-registry.service.d.ts +9 -0
- package/dist/services/social-provider-registry.service.d.ts.map +1 -0
- package/dist/services/social-provider-registry.service.js +30 -0
- package/dist/services/social-provider-registry.service.js.map +1 -0
- package/dist/services/trusted-device.service.d.ts +29 -0
- package/dist/services/trusted-device.service.d.ts.map +1 -0
- package/dist/services/trusted-device.service.js +190 -0
- package/dist/services/trusted-device.service.js.map +1 -0
- package/dist/storage/account-lockout-storage.service.d.ts +16 -0
- package/dist/storage/account-lockout-storage.service.d.ts.map +1 -0
- package/dist/storage/account-lockout-storage.service.js +50 -0
- package/dist/storage/account-lockout-storage.service.js.map +1 -0
- package/dist/storage/index.d.ts +4 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +20 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/memory-storage.adapter.d.ts +33 -0
- package/dist/storage/memory-storage.adapter.d.ts.map +1 -0
- package/dist/storage/memory-storage.adapter.js +195 -0
- package/dist/storage/memory-storage.adapter.js.map +1 -0
- package/dist/storage/rate-limit-storage.service.d.ts +11 -0
- package/dist/storage/rate-limit-storage.service.d.ts.map +1 -0
- package/dist/storage/rate-limit-storage.service.js +33 -0
- package/dist/storage/rate-limit-storage.service.js.map +1 -0
- package/dist/templates/html-template.engine.d.ts +16 -0
- package/dist/templates/html-template.engine.d.ts.map +1 -0
- package/dist/templates/html-template.engine.js +502 -0
- package/dist/templates/html-template.engine.js.map +1 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +18 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/utils/common-passwords.d.ts +4 -0
- package/dist/utils/common-passwords.d.ts.map +1 -0
- package/dist/utils/common-passwords.js +108 -0
- package/dist/utils/common-passwords.js.map +1 -0
- package/dist/utils/context-storage.d.ts +13 -0
- package/dist/utils/context-storage.d.ts.map +1 -0
- package/dist/utils/context-storage.js +54 -0
- package/dist/utils/context-storage.js.map +1 -0
- package/dist/utils/cookie-names.util.d.ts +7 -0
- package/dist/utils/cookie-names.util.d.ts.map +1 -0
- package/dist/utils/cookie-names.util.js +30 -0
- package/dist/utils/cookie-names.util.js.map +1 -0
- package/dist/utils/cookies.util.d.ts +12 -0
- package/dist/utils/cookies.util.d.ts.map +1 -0
- package/dist/utils/cookies.util.js +48 -0
- package/dist/utils/cookies.util.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +24 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/ip-extractor.d.ts +12 -0
- package/dist/utils/ip-extractor.d.ts.map +1 -0
- package/dist/utils/ip-extractor.js +88 -0
- package/dist/utils/ip-extractor.js.map +1 -0
- package/dist/utils/nauth-logger.d.ts +20 -0
- package/dist/utils/nauth-logger.d.ts.map +1 -0
- package/dist/utils/nauth-logger.js +129 -0
- package/dist/utils/nauth-logger.js.map +1 -0
- package/dist/utils/pii-redactor.d.ts +16 -0
- package/dist/utils/pii-redactor.d.ts.map +1 -0
- package/dist/utils/pii-redactor.js +147 -0
- package/dist/utils/pii-redactor.js.map +1 -0
- package/dist/utils/setup/get-repositories.d.ts +16 -0
- package/dist/utils/setup/get-repositories.d.ts.map +1 -0
- package/dist/utils/setup/get-repositories.js +36 -0
- package/dist/utils/setup/get-repositories.js.map +1 -0
- package/dist/utils/setup/init-services.d.ts +41 -0
- package/dist/utils/setup/init-services.d.ts.map +1 -0
- package/dist/utils/setup/init-services.js +107 -0
- package/dist/utils/setup/init-services.js.map +1 -0
- package/dist/utils/setup/init-social.d.ts +13 -0
- package/dist/utils/setup/init-social.d.ts.map +1 -0
- package/dist/utils/setup/init-social.js +77 -0
- package/dist/utils/setup/init-social.js.map +1 -0
- package/dist/utils/setup/init-storage.d.ts +4 -0
- package/dist/utils/setup/init-storage.d.ts.map +1 -0
- package/dist/utils/setup/init-storage.js +79 -0
- package/dist/utils/setup/init-storage.js.map +1 -0
- package/dist/utils/setup/register-mfa.d.ts +5 -0
- package/dist/utils/setup/register-mfa.d.ts.map +1 -0
- package/dist/utils/setup/register-mfa.js +85 -0
- package/dist/utils/setup/register-mfa.js.map +1 -0
- package/dist/utils/setup/run-nauth-migrations.d.ts +5 -0
- package/dist/utils/setup/run-nauth-migrations.d.ts.map +1 -0
- package/dist/utils/setup/run-nauth-migrations.js +67 -0
- package/dist/utils/setup/run-nauth-migrations.js.map +1 -0
- package/dist/utils/token-delivery-policy.d.ts +6 -0
- package/dist/utils/token-delivery-policy.d.ts.map +1 -0
- package/dist/utils/token-delivery-policy.js +15 -0
- package/dist/utils/token-delivery-policy.js.map +1 -0
- package/dist/validators/template.validator.d.ts +7 -0
- package/dist/validators/template.validator.d.ts.map +1 -0
- package/dist/validators/template.validator.js +95 -0
- package/dist/validators/template.validator.js.map +1 -0
- package/jest.config.js +15 -0
- package/jest.setup.ts +6 -0
- package/package.json +73 -0
- package/src/adapters/database-columns.ts +165 -0
- package/src/adapters/express.adapter.ts +385 -0
- package/src/adapters/fastify.adapter.ts +416 -0
- package/src/adapters/index.ts +16 -0
- package/src/adapters/storage.factory.ts +143 -0
- package/src/bootstrap.ts +374 -0
- package/src/dto/auth-challenge.dto.ts +231 -0
- package/src/dto/auth-response.dto.ts +253 -0
- package/src/dto/challenge-response.dto.ts +234 -0
- package/src/dto/change-password-request.dto.ts +50 -0
- package/src/dto/change-password-response.dto.ts +29 -0
- package/src/dto/change-password.dto.ts +57 -0
- package/src/dto/error-response.dto.ts +136 -0
- package/src/dto/get-available-methods.dto.ts +55 -0
- package/src/dto/get-challenge-data-response.dto.ts +28 -0
- package/src/dto/get-challenge-data.dto.ts +69 -0
- package/src/dto/get-client-info.dto.ts +104 -0
- package/src/dto/get-device-token-response.dto.ts +25 -0
- package/src/dto/get-events-by-type.dto.ts +76 -0
- package/src/dto/get-ip-address-response.dto.ts +24 -0
- package/src/dto/get-mfa-status.dto.ts +94 -0
- package/src/dto/get-risk-assessment-history.dto.ts +39 -0
- package/src/dto/get-session-id-response.dto.ts +25 -0
- package/src/dto/get-setup-data-response.dto.ts +31 -0
- package/src/dto/get-setup-data.dto.ts +75 -0
- package/src/dto/get-suspicious-activity.dto.ts +42 -0
- package/src/dto/get-user-agent-response.dto.ts +23 -0
- package/src/dto/get-user-auth-history.dto.ts +95 -0
- package/src/dto/get-user-by-email.dto.ts +61 -0
- package/src/dto/get-user-by-id.dto.ts +46 -0
- package/src/dto/get-user-devices.dto.ts +53 -0
- package/src/dto/get-user-response.dto.ts +17 -0
- package/src/dto/has-provider.dto.ts +56 -0
- package/src/dto/index.ts +57 -0
- package/src/dto/is-trusted-device-response.dto.ts +34 -0
- package/src/dto/list-providers-response.dto.ts +23 -0
- package/src/dto/login.dto.ts +95 -0
- package/src/dto/logout-all-response.dto.ts +24 -0
- package/src/dto/logout-all.dto.ts +65 -0
- package/src/dto/logout-response.dto.ts +25 -0
- package/src/dto/logout.dto.ts +64 -0
- package/src/dto/refresh-token.dto.ts +36 -0
- package/src/dto/remove-devices.dto.ts +85 -0
- package/src/dto/resend-code-response.dto.ts +32 -0
- package/src/dto/resend-code.dto.ts +51 -0
- package/src/dto/reset-password.dto.ts +115 -0
- package/src/dto/respond-challenge.dto.ts +272 -0
- package/src/dto/set-mfa-exemption.dto.ts +112 -0
- package/src/dto/set-must-change-password-response.dto.ts +27 -0
- package/src/dto/set-must-change-password.dto.ts +46 -0
- package/src/dto/set-preferred-method.dto.ts +80 -0
- package/src/dto/setup-mfa.dto.ts +98 -0
- package/src/dto/signup.dto.ts +174 -0
- package/src/dto/social-auth.dto.ts +422 -0
- package/src/dto/trust-device-response.dto.ts +30 -0
- package/src/dto/trust-device.dto.ts +9 -0
- package/src/dto/update-user-attributes-request.dto.ts +51 -0
- package/src/dto/user-response.dto.ts +138 -0
- package/src/dto/user-update.dto.ts +222 -0
- package/src/dto/verify-email.dto.ts +313 -0
- package/src/dto/verify-mfa-code.dto.ts +103 -0
- package/src/dto/verify-phone-by-sub.dto.ts +78 -0
- package/src/dto/verify-phone.dto.ts +245 -0
- package/src/entities/auth-audit.entity.ts +232 -0
- package/src/entities/challenge-session.entity.ts +116 -0
- package/src/entities/index.ts +29 -0
- package/src/entities/login-attempt.entity.ts +64 -0
- package/src/entities/mfa-device.entity.ts +151 -0
- package/src/entities/rate-limit.entity.ts +44 -0
- package/src/entities/session.entity.ts +180 -0
- package/src/entities/social-account.entity.ts +96 -0
- package/src/entities/storage-lock.entity.ts +39 -0
- package/src/entities/trusted-device.entity.ts +112 -0
- package/src/entities/user.entity.ts +243 -0
- package/src/entities/verification-token.entity.ts +141 -0
- package/src/enums/auth-audit-event-type.enum.ts +360 -0
- package/src/enums/error-codes.enum.ts +420 -0
- package/src/enums/mfa-method.enum.ts +97 -0
- package/src/enums/risk-factor.enum.ts +111 -0
- package/src/exceptions/nauth.exception.ts +231 -0
- package/src/handlers/auth.handler.ts +260 -0
- package/src/handlers/client-info.handler.ts +101 -0
- package/src/handlers/csrf.handler.ts +156 -0
- package/src/handlers/token-delivery.handler.ts +118 -0
- package/src/index.ts +118 -0
- package/src/interfaces/client-info.interface.ts +85 -0
- package/src/interfaces/config.interface.ts +2135 -0
- package/src/interfaces/entities.interface.ts +226 -0
- package/src/interfaces/index.ts +15 -0
- package/src/interfaces/logger.interface.ts +283 -0
- package/src/interfaces/mfa-provider.interface.ts +154 -0
- package/src/interfaces/oauth.interface.ts +148 -0
- package/src/interfaces/provider.interface.ts +47 -0
- package/src/interfaces/social-auth-provider.interface.ts +131 -0
- package/src/interfaces/storage-adapter.interface.ts +82 -0
- package/src/interfaces/template.interface.ts +510 -0
- package/src/interfaces/token-verifier.interface.ts +110 -0
- package/src/internal.ts +178 -0
- package/src/platform/interfaces.ts +299 -0
- package/src/schemas/auth-config.schema.ts +646 -0
- package/src/services/adaptive-mfa-decision.service.spec.ts +1058 -0
- package/src/services/adaptive-mfa-decision.service.ts +457 -0
- package/src/services/auth-audit.service.spec.ts +675 -0
- package/src/services/auth-audit.service.ts +558 -0
- package/src/services/auth-challenge-helper.service.spec.ts +3227 -0
- package/src/services/auth-challenge-helper.service.ts +825 -0
- package/src/services/auth-flow-context-builder.service.ts +520 -0
- package/src/services/auth-flow-rules.ts +202 -0
- package/src/services/auth-flow-state-definitions.ts +190 -0
- package/src/services/auth-flow-state-machine.service.ts +207 -0
- package/src/services/auth-flow-state-machine.types.ts +316 -0
- package/src/services/auth.service.spec.ts +4195 -0
- package/src/services/auth.service.ts +3727 -0
- package/src/services/challenge.service.spec.ts +1363 -0
- package/src/services/challenge.service.ts +696 -0
- package/src/services/client-info.service.spec.ts +572 -0
- package/src/services/client-info.service.ts +374 -0
- package/src/services/csrf.service.ts +54 -0
- package/src/services/email-verification.service.spec.ts +1229 -0
- package/src/services/email-verification.service.ts +578 -0
- package/src/services/geo-location.service.spec.ts +603 -0
- package/src/services/geo-location.service.ts +599 -0
- package/src/services/index.ts +13 -0
- package/src/services/jwt.service.spec.ts +882 -0
- package/src/services/jwt.service.ts +621 -0
- package/src/services/mfa-base.service.spec.ts +246 -0
- package/src/services/mfa-base.service.ts +611 -0
- package/src/services/mfa.service.spec.ts +693 -0
- package/src/services/mfa.service.ts +960 -0
- package/src/services/password.service.spec.ts +166 -0
- package/src/services/password.service.ts +309 -0
- package/src/services/phone-verification.service.spec.ts +1120 -0
- package/src/services/phone-verification.service.ts +751 -0
- package/src/services/risk-detection.service.spec.ts +1292 -0
- package/src/services/risk-detection.service.ts +1012 -0
- package/src/services/risk-scoring.service.spec.ts +204 -0
- package/src/services/risk-scoring.service.ts +131 -0
- package/src/services/session.service.spec.ts +1293 -0
- package/src/services/session.service.ts +803 -0
- package/src/services/social-account.service.spec.ts +725 -0
- package/src/services/social-auth-base.service.spec.ts +418 -0
- package/src/services/social-auth-base.service.ts +581 -0
- package/src/services/social-auth.service.spec.ts +238 -0
- package/src/services/social-auth.service.ts +436 -0
- package/src/services/social-provider-registry.service.spec.ts +238 -0
- package/src/services/social-provider-registry.service.ts +122 -0
- package/src/services/trusted-device.service.spec.ts +505 -0
- package/src/services/trusted-device.service.ts +339 -0
- package/src/storage/account-lockout-storage.service.spec.ts +310 -0
- package/src/storage/account-lockout-storage.service.ts +89 -0
- package/src/storage/index.ts +3 -0
- package/src/storage/memory-storage.adapter.ts +443 -0
- package/src/storage/rate-limit-storage.service.spec.ts +247 -0
- package/src/storage/rate-limit-storage.service.ts +38 -0
- package/src/templates/html-template.engine.spec.ts +161 -0
- package/src/templates/html-template.engine.ts +688 -0
- package/src/templates/index.ts +7 -0
- package/src/utils/common-passwords.spec.ts +230 -0
- package/src/utils/common-passwords.ts +170 -0
- package/src/utils/context-storage.ts +188 -0
- package/src/utils/cookie-names.util.ts +67 -0
- package/src/utils/cookies.util.ts +94 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/ip-extractor.spec.ts +330 -0
- package/src/utils/ip-extractor.ts +220 -0
- package/src/utils/nauth-logger.spec.ts +388 -0
- package/src/utils/nauth-logger.ts +215 -0
- package/src/utils/pii-redactor.spec.ts +130 -0
- package/src/utils/pii-redactor.ts +288 -0
- package/src/utils/setup/get-repositories.ts +140 -0
- package/src/utils/setup/init-services.ts +422 -0
- package/src/utils/setup/init-social.ts +189 -0
- package/src/utils/setup/init-storage.ts +94 -0
- package/src/utils/setup/register-mfa.ts +165 -0
- package/src/utils/setup/run-nauth-migrations.ts +61 -0
- package/src/utils/token-delivery-policy.ts +38 -0
- package/src/validators/template.validator.ts +219 -0
- package/tsconfig.json +37 -0
- package/tsconfig.lint.json +6 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
import { Repository } from 'typeorm';
|
|
2
|
+
import { BaseMFADevice } from '../entities';
|
|
3
|
+
import { AuthResponseDTO } from '../dto/auth-response.dto';
|
|
4
|
+
import { AuthChallenge } from '../dto/auth-challenge.dto';
|
|
5
|
+
import { SendVerificationEmailDTO } from '../dto/verify-email.dto';
|
|
6
|
+
import { SendVerificationSMSDTO } from '../dto/verify-phone.dto';
|
|
7
|
+
import { IUser, IMFADevice } from '../interfaces/entities.interface';
|
|
8
|
+
import { ChallengeService } from './challenge.service';
|
|
9
|
+
import { JwtService } from './jwt.service';
|
|
10
|
+
import { SessionService } from './session.service';
|
|
11
|
+
import { EmailVerificationService } from './email-verification.service';
|
|
12
|
+
import { PhoneVerificationService } from './phone-verification.service';
|
|
13
|
+
import { ClientInfoService } from './client-info.service';
|
|
14
|
+
import { NAuthConfig } from '../interfaces/config.interface';
|
|
15
|
+
import { NAuthLogger } from '../utils/nauth-logger';
|
|
16
|
+
import { NAuthException } from '../exceptions/nauth.exception';
|
|
17
|
+
import { AuthErrorCode } from '../enums/error-codes.enum';
|
|
18
|
+
import { MFAMethod, MFADeviceMethod, MFAVerificationMethod, MFADeviceMethods } from '../enums/mfa-method.enum';
|
|
19
|
+
import { AuthFlowStateMachineService } from './auth-flow-state-machine.service';
|
|
20
|
+
import { AuthFlowContextBuilder } from './auth-flow-context-builder.service';
|
|
21
|
+
import { AuthFlowState, AuthFlowContext } from './auth-flow-state-machine.types';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Helper service for challenge-response authentication flows
|
|
25
|
+
*
|
|
26
|
+
* This service determines if a user needs to complete challenges
|
|
27
|
+
* before full authentication can be granted, and generates appropriate
|
|
28
|
+
* responses including MFA challenges.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const response = await challengeHelper.determineAuthResponse(
|
|
33
|
+
* user,
|
|
34
|
+
* 'login',
|
|
35
|
+
* { ipAddress: '1.2.3.4' }
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export class AuthChallengeHelperService {
|
|
40
|
+
constructor(
|
|
41
|
+
private readonly challengeService: ChallengeService,
|
|
42
|
+
private readonly jwtService: JwtService,
|
|
43
|
+
private readonly sessionService: SessionService,
|
|
44
|
+
private readonly mfaDeviceRepository: Repository<BaseMFADevice>,
|
|
45
|
+
private readonly logger: NAuthLogger,
|
|
46
|
+
private readonly stateMachine: AuthFlowStateMachineService,
|
|
47
|
+
private readonly contextBuilder: AuthFlowContextBuilder,
|
|
48
|
+
private readonly clientInfoService: ClientInfoService,
|
|
49
|
+
private readonly emailVerificationService?: EmailVerificationService,
|
|
50
|
+
private readonly phoneVerificationService?: PhoneVerificationService, // Optional - only available when SMS provider is configured
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// OLD METHODS DELETED - Replaced by state machine
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// determinePendingChallenges() - DELETED (replaced by state machine)
|
|
57
|
+
// isMFASetupRequired() - DELETED (replaced by state machine)
|
|
58
|
+
// checkMFARequirement() - DELETED (replaced by state machine)
|
|
59
|
+
// All challenge determination is now handled by determineAuthResponse() using state machine
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create challenge response for authentication
|
|
63
|
+
*
|
|
64
|
+
* Generates a challenge session and returns challenge details to client.
|
|
65
|
+
* Sends verification codes when challenges are created to ensure sequential flow.
|
|
66
|
+
*
|
|
67
|
+
* @param user - User who needs to complete challenges
|
|
68
|
+
* @param challengeName - Type of challenge
|
|
69
|
+
* @param config - Auth configuration
|
|
70
|
+
* @param authMethod - Authentication method ('password' or 'social')
|
|
71
|
+
* @param authProvider - Provider name for social auth (e.g., 'google', 'facebook')
|
|
72
|
+
* @returns Challenge response DTO
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const response = await challengeHelper.createChallengeResponse(
|
|
77
|
+
* user,
|
|
78
|
+
* AuthChallenge.VERIFY_EMAIL,
|
|
79
|
+
* config,
|
|
80
|
+
* 'social',
|
|
81
|
+
* 'google'
|
|
82
|
+
* );
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
async createChallengeResponse(
|
|
86
|
+
user: IUser,
|
|
87
|
+
challengeName: AuthChallenge,
|
|
88
|
+
config: NAuthConfig,
|
|
89
|
+
authMethod: 'password' | 'social' = 'password',
|
|
90
|
+
authProvider?: string,
|
|
91
|
+
skipAutoSend?: boolean,
|
|
92
|
+
): Promise<AuthResponseDTO> {
|
|
93
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
94
|
+
// Note: ClientInfoService is used transparently by ChallengeService and AuditService
|
|
95
|
+
|
|
96
|
+
// ============================================================================
|
|
97
|
+
// STEP 1: Create challenge session FIRST (before sending codes)
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// This ensures the session exists before any verification codes are sent.
|
|
100
|
+
// Creating the session first is critical for proper audit trail and session tracking.
|
|
101
|
+
this.logger?.debug?.(
|
|
102
|
+
`Creating challenge with authMethod=${authMethod}, authProvider=${authProvider || 'none'} for user ${user.sub}`,
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
106
|
+
const challengeSession = await this.challengeService.createChallengeSession(user, challengeName, {
|
|
107
|
+
email: user.email,
|
|
108
|
+
phone: user.phone,
|
|
109
|
+
authMethod, // Store auth method for challenge completion flow
|
|
110
|
+
authProvider, // Store provider for social auth (e.g., 'google', 'facebook')
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// STEP 2: Send verification codes AFTER session is created
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// This ensures codes are sent at the right time:
|
|
117
|
+
// - Email code sent when VERIFY_EMAIL challenge is created
|
|
118
|
+
// - Phone code sent when VERIFY_PHONE challenge is created (after email is verified)
|
|
119
|
+
// This prevents sending both codes at once, avoiding user confusion.
|
|
120
|
+
// Challenges are sequential: first VERIFY_EMAIL, then VERIFY_PHONE
|
|
121
|
+
if (challengeName === AuthChallenge.VERIFY_EMAIL && this.emailVerificationService) {
|
|
122
|
+
this.logger?.log?.(`📧 Sending verification email to: ${user.email}`);
|
|
123
|
+
// Fire and forget - don't block challenge response
|
|
124
|
+
const emailDto = Object.assign(new SendVerificationEmailDTO(), {
|
|
125
|
+
sub: user.sub,
|
|
126
|
+
baseUrl: undefined,
|
|
127
|
+
challengeSessionId: challengeSession.id, // Link verification token to this challenge session
|
|
128
|
+
});
|
|
129
|
+
this.emailVerificationService
|
|
130
|
+
.sendVerificationEmail(emailDto)
|
|
131
|
+
.then(() => {
|
|
132
|
+
this.logger?.log?.(`Verification email sent successfully to: ${user.email}`);
|
|
133
|
+
})
|
|
134
|
+
.catch((error: unknown) => {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
136
|
+
this.logger?.error?.(`Failed to send verification email to ${user.email}: ${errorMessage}`);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Skip auto-send if SMS was already sent (e.g., during phone collection)
|
|
141
|
+
if (!skipAutoSend && challengeName === AuthChallenge.VERIFY_PHONE && this.phoneVerificationService && user.phone) {
|
|
142
|
+
this.logger?.log?.(`Sending verification SMS to: ${user.phone}`);
|
|
143
|
+
// Fire and forget - don't block challenge response
|
|
144
|
+
const smsDto = Object.assign(new SendVerificationSMSDTO(), {
|
|
145
|
+
sub: user.sub,
|
|
146
|
+
challengeSessionId: challengeSession.id, // Link verification token to this challenge session
|
|
147
|
+
});
|
|
148
|
+
this.phoneVerificationService
|
|
149
|
+
.sendVerificationSMS(smsDto)
|
|
150
|
+
.then(() => {
|
|
151
|
+
this.logger?.log?.(`Verification SMS sent successfully to: ${user.phone}`);
|
|
152
|
+
})
|
|
153
|
+
.catch((error: unknown) => {
|
|
154
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
155
|
+
this.logger?.error?.(`Failed to send verification SMS to ${user.phone}: ${errorMessage}`);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ============================================================================
|
|
160
|
+
// STEP 3: Send MFA challenge code for MFA_REQUIRED (if SMS is preferred method)
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// When user logs in and MFA verification is required, automatically send SMS code
|
|
163
|
+
// if SMS is their preferred MFA method. This provides better UX by not requiring
|
|
164
|
+
// a separate API call to trigger code sending.
|
|
165
|
+
//
|
|
166
|
+
// Note: MFA_REQUIRED challenges are handled by createMFAChallengeResponse()
|
|
167
|
+
// which includes auto-send SMS logic
|
|
168
|
+
|
|
169
|
+
// Build challenge parameters
|
|
170
|
+
// Note: Type is Record<string, unknown> to allow arrays (e.g., allowedMethods for MFA)
|
|
171
|
+
const challengeParameters: Record<string, unknown> = {};
|
|
172
|
+
|
|
173
|
+
switch (challengeName) {
|
|
174
|
+
case AuthChallenge.VERIFY_EMAIL:
|
|
175
|
+
challengeParameters.email = user.email;
|
|
176
|
+
challengeParameters.codeDeliveryDestination = this.challengeService.maskEmail(user.email);
|
|
177
|
+
break;
|
|
178
|
+
|
|
179
|
+
case AuthChallenge.VERIFY_PHONE:
|
|
180
|
+
challengeParameters.phone = user.phone || undefined;
|
|
181
|
+
challengeParameters.codeDeliveryDestination = user.phone
|
|
182
|
+
? this.challengeService.maskPhone(user.phone)
|
|
183
|
+
: undefined;
|
|
184
|
+
// If no phone, indicate user must provide it first
|
|
185
|
+
if (!user.phone) {
|
|
186
|
+
challengeParameters.requiresPhoneCollection = 'true';
|
|
187
|
+
challengeParameters.instructions = 'You must add a phone number and verify it to continue';
|
|
188
|
+
}
|
|
189
|
+
break;
|
|
190
|
+
|
|
191
|
+
case AuthChallenge.MFA_REQUIRED:
|
|
192
|
+
challengeParameters.instructions = 'Multi-factor authentication is required';
|
|
193
|
+
// Include masked phone if SMS is preferred method
|
|
194
|
+
if (user.preferredMfaMethod === 'sms' && user.phone) {
|
|
195
|
+
challengeParameters.codeDeliveryDestination = this.challengeService.maskPhone(user.phone);
|
|
196
|
+
}
|
|
197
|
+
// Include masked email if Email is preferred method
|
|
198
|
+
if (user.preferredMfaMethod === 'email' && user.email) {
|
|
199
|
+
challengeParameters.codeDeliveryDestination = this.challengeService.maskEmail(user.email);
|
|
200
|
+
}
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case AuthChallenge.MFA_SETUP_REQUIRED: {
|
|
204
|
+
const allowedMethods = config.mfa?.allowedMethods || [...MFADeviceMethods];
|
|
205
|
+
challengeParameters.allowedMethods = allowedMethods;
|
|
206
|
+
challengeParameters.instructions = 'Multi-factor authentication setup is required before you can login';
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case AuthChallenge.FORCE_CHANGE_PASSWORD:
|
|
211
|
+
challengeParameters.instructions = 'You must change your password before continuing';
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const response: AuthResponseDTO = {
|
|
216
|
+
challengeName,
|
|
217
|
+
session: challengeSession.sessionToken,
|
|
218
|
+
challengeParameters,
|
|
219
|
+
userSub: user.sub,
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return response;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// MFA Challenge Support
|
|
227
|
+
// ============================================================================
|
|
228
|
+
// checkMFARequirement() - DELETED (replaced by state machine)
|
|
229
|
+
// All MFA requirement checking is now handled by state machine in determineAuthResponse()
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Create MFA setup challenge response
|
|
233
|
+
*
|
|
234
|
+
* Generates challenge session for MFA setup requirement.
|
|
235
|
+
* User must set up MFA before being allowed to login.
|
|
236
|
+
*
|
|
237
|
+
* @param user - User requiring MFA setup
|
|
238
|
+
* @param config - Auth configuration
|
|
239
|
+
* @param authMethod - Authentication method ('password' or 'social')
|
|
240
|
+
* @param authProvider - Provider name for social auth (e.g., 'google', 'facebook')
|
|
241
|
+
* @returns MFA setup challenge response
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* ```typescript
|
|
245
|
+
* const response = await challengeHelper.createMFASetupChallengeResponse(
|
|
246
|
+
* user,
|
|
247
|
+
* config,
|
|
248
|
+
* 'social',
|
|
249
|
+
* 'google'
|
|
250
|
+
* );
|
|
251
|
+
* // Returns: { challengeName: 'MFA_SETUP_REQUIRED', session: '...', challengeParameters: {...} }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
async createMFASetupChallengeResponse(
|
|
255
|
+
user: IUser,
|
|
256
|
+
config: NAuthConfig,
|
|
257
|
+
authMethod: 'password' | 'social' = 'password',
|
|
258
|
+
authProvider?: string,
|
|
259
|
+
): Promise<AuthResponseDTO> {
|
|
260
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
261
|
+
// Note: ClientInfoService is used transparently by ChallengeService and AuditService
|
|
262
|
+
this.logger?.log?.(`Creating MFA setup challenge for user: ${user.sub}`);
|
|
263
|
+
|
|
264
|
+
const allowedMethods = config.mfa?.allowedMethods || [...MFADeviceMethods];
|
|
265
|
+
|
|
266
|
+
// Create challenge session with auth context
|
|
267
|
+
this.logger?.debug?.(
|
|
268
|
+
`Creating MFA setup challenge with authMethod=${authMethod}, authProvider=${authProvider || 'none'} for user ${user.sub}`,
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
272
|
+
const challengeSession = await this.challengeService.createChallengeSession(
|
|
273
|
+
user,
|
|
274
|
+
AuthChallenge.MFA_SETUP_REQUIRED,
|
|
275
|
+
{
|
|
276
|
+
allowedMethods,
|
|
277
|
+
requiresSetup: true,
|
|
278
|
+
authMethod, // Store auth method for challenge completion flow
|
|
279
|
+
authProvider, // Store provider for social auth
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
this.logger?.log?.(`MFA setup challenge created for user: ${user.sub}`);
|
|
284
|
+
|
|
285
|
+
// Return challenge response
|
|
286
|
+
return {
|
|
287
|
+
challengeName: AuthChallenge.MFA_SETUP_REQUIRED,
|
|
288
|
+
session: challengeSession.sessionToken,
|
|
289
|
+
challengeParameters: {
|
|
290
|
+
allowedMethods,
|
|
291
|
+
instructions: 'Multi-factor authentication setup is required before you can login',
|
|
292
|
+
},
|
|
293
|
+
userSub: user.sub,
|
|
294
|
+
} as AuthResponseDTO;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Create MFA challenge response
|
|
299
|
+
*
|
|
300
|
+
* Generates challenge session for MFA verification.
|
|
301
|
+
* Returns available MFA methods and challenge parameters.
|
|
302
|
+
*
|
|
303
|
+
* @param user - User requiring MFA
|
|
304
|
+
* @returns MFA challenge response
|
|
305
|
+
* @remarks Client info (ipAddress, userAgent) is automatically extracted from ClientInfoService context
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const response = await challengeHelper.createMFAChallengeResponse(
|
|
310
|
+
* user,
|
|
311
|
+
* '1.2.3.4',
|
|
312
|
+
* 'Mozilla/5.0...'
|
|
313
|
+
* );
|
|
314
|
+
* // Returns: { challengeName: 'MFA_REQUIRED', session: '...', challengeParameters: {...} }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
async createMFAChallengeResponse(user: IUser): Promise<AuthResponseDTO> {
|
|
318
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
319
|
+
// Note: ClientInfoService is used transparently by ChallengeService and AuditService
|
|
320
|
+
this.logger?.log?.(`Creating MFA challenge for user: ${user.sub}`);
|
|
321
|
+
|
|
322
|
+
// Get user's active MFA devices
|
|
323
|
+
const devices = (await this.mfaDeviceRepository.find({
|
|
324
|
+
where: { userId: user.id, isActive: true },
|
|
325
|
+
order: { isPrimary: 'DESC', lastUsedAt: 'DESC' },
|
|
326
|
+
})) as unknown as IMFADevice[];
|
|
327
|
+
|
|
328
|
+
if (devices.length === 0) {
|
|
329
|
+
this.logger?.warn?.(`User has MFA enabled but no active devices: ${user.sub}`);
|
|
330
|
+
// User has MFA enabled but no devices - should not happen
|
|
331
|
+
// Allow login and let them set up MFA
|
|
332
|
+
throw new NAuthException(AuthErrorCode.INTERNAL_ERROR, 'MFA enabled but no devices configured');
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Get available methods (device types only - no backup)
|
|
336
|
+
const deviceMethods = [...new Set(devices.map((d) => d.type))] as MFADeviceMethod[];
|
|
337
|
+
|
|
338
|
+
// Build full available methods list (including backup if available)
|
|
339
|
+
const availableMethods: MFAVerificationMethod[] = [...deviceMethods];
|
|
340
|
+
if (user.backupCodes && user.backupCodes.length > 0) {
|
|
341
|
+
availableMethods.push(MFAMethod.BACKUP);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Debug logging for troubleshooting
|
|
345
|
+
this.logger?.debug?.(
|
|
346
|
+
`MFA challenge for user ${user.sub}: preferredMfaMethod=${user.preferredMfaMethod}, deviceMethods=[${deviceMethods.join(', ')}], devices=[${devices.map((d) => `${d.type}${d.isPrimary ? '(primary)' : ''}`).join(', ')}]`,
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
// Determine preferred method - prioritize user.preferredMfaMethod over primaryDevice
|
|
350
|
+
// This ensures that when user explicitly sets a preferred method, it's respected
|
|
351
|
+
let preferredMethod: string;
|
|
352
|
+
|
|
353
|
+
// Normalize preferred method to lowercase for comparison (database might store in different case)
|
|
354
|
+
const normalizedPreferredMethod = user.preferredMfaMethod?.toLowerCase();
|
|
355
|
+
|
|
356
|
+
// Check if user has a preferred method and it's available
|
|
357
|
+
if (
|
|
358
|
+
normalizedPreferredMethod &&
|
|
359
|
+
(normalizedPreferredMethod === MFAMethod.TOTP ||
|
|
360
|
+
normalizedPreferredMethod === MFAMethod.SMS ||
|
|
361
|
+
normalizedPreferredMethod === MFAMethod.EMAIL ||
|
|
362
|
+
normalizedPreferredMethod === MFAMethod.PASSKEY) &&
|
|
363
|
+
deviceMethods.some((m) => m.toLowerCase() === normalizedPreferredMethod)
|
|
364
|
+
) {
|
|
365
|
+
// User has explicitly set a preferred method and it's available
|
|
366
|
+
// Find the actual method from deviceMethods to ensure case consistency
|
|
367
|
+
preferredMethod =
|
|
368
|
+
deviceMethods.find((m) => m.toLowerCase() === normalizedPreferredMethod) || normalizedPreferredMethod;
|
|
369
|
+
this.logger?.debug?.(
|
|
370
|
+
`Using user preferred MFA method: ${preferredMethod} (from user.preferredMfaMethod: ${user.preferredMfaMethod})`,
|
|
371
|
+
);
|
|
372
|
+
} else {
|
|
373
|
+
// Fallback to primary device or first available method
|
|
374
|
+
const primaryDevice = devices.find((d) => d.isPrimary);
|
|
375
|
+
preferredMethod = primaryDevice?.type || deviceMethods[0];
|
|
376
|
+
this.logger?.debug?.(
|
|
377
|
+
`Using fallback MFA method: ${preferredMethod} (preferred: ${user.preferredMfaMethod}, available: ${deviceMethods.join(', ')})`,
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Get masked phone if SMS is available
|
|
382
|
+
let maskedPhone: string | undefined;
|
|
383
|
+
const smsDevice = devices.find((d) => d.type === MFAMethod.SMS && d.phoneNumber);
|
|
384
|
+
if (smsDevice?.phoneNumber) {
|
|
385
|
+
const digits = smsDevice.phoneNumber.replace(/\D/g, '');
|
|
386
|
+
maskedPhone = digits.length >= 4 ? `***-***-${digits.slice(-4)}` : smsDevice.phoneNumber;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Get masked email if Email is available
|
|
390
|
+
let maskedEmail: string | undefined;
|
|
391
|
+
const emailDevice = devices.find((d) => d.type === MFAMethod.EMAIL && d.email);
|
|
392
|
+
const emailToMask = emailDevice?.email || user.email; // Fallback to user.email if device doesn't have it
|
|
393
|
+
if (emailToMask) {
|
|
394
|
+
// Mask email: show first char and domain (e.g., u***r@example.com)
|
|
395
|
+
const [localPart, domain] = emailToMask.split('@');
|
|
396
|
+
if (localPart && domain) {
|
|
397
|
+
const firstChar = localPart[0];
|
|
398
|
+
const lastChar = localPart[localPart.length - 1];
|
|
399
|
+
maskedEmail = localPart.length > 2 ? `${firstChar}***${lastChar}@${domain}` : `${firstChar}***@${domain}`;
|
|
400
|
+
} else {
|
|
401
|
+
maskedEmail = emailToMask;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Create challenge session
|
|
406
|
+
// Client info (ipAddress, userAgent) automatically extracted from ClientInfoService
|
|
407
|
+
// Store preferred method in metadata for resend endpoint to know which method to use
|
|
408
|
+
const challengeSession = await this.challengeService.createChallengeSession(user, AuthChallenge.MFA_REQUIRED, {
|
|
409
|
+
availableMethods,
|
|
410
|
+
preferredMethod,
|
|
411
|
+
maskedPhone,
|
|
412
|
+
maskedEmail,
|
|
413
|
+
method: preferredMethod, // Store method in metadata for resend endpoint
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
this.logger?.log?.(`MFA challenge created for user: ${user.sub}`);
|
|
417
|
+
|
|
418
|
+
// ============================================================================
|
|
419
|
+
// Auto-send SMS code if SMS is the preferred method
|
|
420
|
+
// ============================================================================
|
|
421
|
+
// Automatically send SMS code if:
|
|
422
|
+
// 1. SMS is user's preferred MFA method, OR
|
|
423
|
+
// 2. SMS is the ONLY MFA method they have setup
|
|
424
|
+
//
|
|
425
|
+
// This provides better UX by not requiring a separate API call to trigger code sending.
|
|
426
|
+
const smsIsPreferred = preferredMethod.toLowerCase() === 'sms';
|
|
427
|
+
const smsIsOnly = deviceMethods.length === 1 && deviceMethods[0].toLowerCase() === 'sms';
|
|
428
|
+
|
|
429
|
+
if ((smsIsPreferred || smsIsOnly) && this.phoneVerificationService && user.phone) {
|
|
430
|
+
this.logger?.log?.(
|
|
431
|
+
`Auto-sending MFA SMS code to user ${user.sub} (preferred=${smsIsPreferred}, only=${smsIsOnly})`,
|
|
432
|
+
);
|
|
433
|
+
// Fire and forget - don't block challenge response
|
|
434
|
+
// Use PhoneVerificationService which handles SMS sending, rate limits, and token storage
|
|
435
|
+
// skipAlreadyVerifiedCheck=true because phone is already verified but we need MFA code
|
|
436
|
+
const smsDto = Object.assign(new SendVerificationSMSDTO(), {
|
|
437
|
+
sub: user.sub,
|
|
438
|
+
skipAlreadyVerifiedCheck: true,
|
|
439
|
+
challengeSessionId: challengeSession.id, // Link MFA SMS code to this challenge session
|
|
440
|
+
});
|
|
441
|
+
this.phoneVerificationService
|
|
442
|
+
.sendVerificationSMS(smsDto)
|
|
443
|
+
.then(() => {
|
|
444
|
+
this.logger?.log?.(`MFA SMS code sent successfully to user ${user.sub}`);
|
|
445
|
+
})
|
|
446
|
+
.catch((error: unknown) => {
|
|
447
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
448
|
+
this.logger?.error?.(`Failed to send MFA SMS code to user ${user.sub}: ${errorMessage}`);
|
|
449
|
+
});
|
|
450
|
+
} else {
|
|
451
|
+
this.logger?.debug?.(
|
|
452
|
+
`Skipped auto-send MFA SMS for user ${user.sub}: ` +
|
|
453
|
+
`phoneService=${!!this.phoneVerificationService}, ` +
|
|
454
|
+
`preferredMethod=${preferredMethod}, ` +
|
|
455
|
+
`smsIsPreferred=${smsIsPreferred}, ` +
|
|
456
|
+
`smsIsOnly=${smsIsOnly}, ` +
|
|
457
|
+
`deviceMethods=[${deviceMethods.join(', ')}], ` +
|
|
458
|
+
`phone=${!!user.phone}`,
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// ============================================================================
|
|
463
|
+
// Auto-send Email code if Email is the preferred method
|
|
464
|
+
// ============================================================================
|
|
465
|
+
// Automatically send Email code if:
|
|
466
|
+
// 1. Email is user's preferred MFA method, OR
|
|
467
|
+
// 2. Email is the ONLY MFA method they have setup
|
|
468
|
+
//
|
|
469
|
+
// This provides better UX by not requiring a separate API call to trigger code sending.
|
|
470
|
+
const emailIsPreferred = preferredMethod.toLowerCase() === 'email';
|
|
471
|
+
const emailIsOnly = deviceMethods.length === 1 && deviceMethods[0].toLowerCase() === 'email';
|
|
472
|
+
|
|
473
|
+
if ((emailIsPreferred || emailIsOnly) && this.emailVerificationService && user.email) {
|
|
474
|
+
this.logger?.log?.(
|
|
475
|
+
`Auto-sending MFA Email code to user ${user.sub} (preferred=${emailIsPreferred}, only=${emailIsOnly})`,
|
|
476
|
+
);
|
|
477
|
+
// Fire and forget - don't block challenge response
|
|
478
|
+
// Use EmailVerificationService which handles email sending, rate limits, and token storage
|
|
479
|
+
// skipAlreadyVerifiedCheck=true because email is already verified but we need MFA code
|
|
480
|
+
const emailDto = Object.assign(new SendVerificationEmailDTO(), {
|
|
481
|
+
sub: user.sub,
|
|
482
|
+
baseUrl: undefined,
|
|
483
|
+
skipAlreadyVerifiedCheck: true,
|
|
484
|
+
challengeSessionId: challengeSession.id, // Link MFA email code to this challenge session
|
|
485
|
+
});
|
|
486
|
+
this.emailVerificationService
|
|
487
|
+
.sendVerificationEmail(emailDto)
|
|
488
|
+
.then(() => {
|
|
489
|
+
this.logger?.log?.(`MFA Email code sent successfully to user ${user.sub}`);
|
|
490
|
+
})
|
|
491
|
+
.catch((error: unknown) => {
|
|
492
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
493
|
+
this.logger?.error?.(`Failed to send MFA Email code to user ${user.sub}: ${errorMessage}`);
|
|
494
|
+
});
|
|
495
|
+
} else {
|
|
496
|
+
this.logger?.debug?.(
|
|
497
|
+
`Skipped auto-send MFA Email for user ${user.sub}: ` +
|
|
498
|
+
`emailService=${!!this.emailVerificationService}, ` +
|
|
499
|
+
`preferredMethod=${preferredMethod}, ` +
|
|
500
|
+
`emailIsPreferred=${emailIsPreferred}, ` +
|
|
501
|
+
`emailIsOnly=${emailIsOnly}, ` +
|
|
502
|
+
`deviceMethods=[${deviceMethods.join(', ')}], ` +
|
|
503
|
+
`email=${!!user.email}`,
|
|
504
|
+
);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Return challenge response
|
|
508
|
+
// Always include maskedEmail if email is preferred, even if undefined (frontend can use user.email)
|
|
509
|
+
const challengeParams: Record<string, unknown> = {
|
|
510
|
+
availableMethods,
|
|
511
|
+
preferredMethod: preferredMethod as MFADeviceMethod,
|
|
512
|
+
};
|
|
513
|
+
if (maskedPhone) {
|
|
514
|
+
challengeParams.maskedPhone = maskedPhone;
|
|
515
|
+
}
|
|
516
|
+
if (maskedEmail || preferredMethod.toLowerCase() === 'email') {
|
|
517
|
+
// Include maskedEmail if available, or if email is preferred (frontend will handle display)
|
|
518
|
+
challengeParams.maskedEmail = maskedEmail || user.email || '';
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return {
|
|
522
|
+
challengeName: AuthChallenge.MFA_REQUIRED,
|
|
523
|
+
session: challengeSession.sessionToken,
|
|
524
|
+
challengeParameters: challengeParams,
|
|
525
|
+
} as AuthResponseDTO;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// ============================================================================
|
|
529
|
+
// Success Response
|
|
530
|
+
// ============================================================================
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Create successful authentication response with tokens
|
|
534
|
+
*
|
|
535
|
+
* Generates tokens and session for fully authenticated user.
|
|
536
|
+
*
|
|
537
|
+
* @param user - Authenticated user
|
|
538
|
+
* @param deviceToken - Device token (optional)
|
|
539
|
+
* @param isTrusted - Whether device is trusted (optional)
|
|
540
|
+
* @param isSocialLogin - Whether this is a social login (optional)
|
|
541
|
+
* @param metadata - Response metadata (optional)
|
|
542
|
+
* @returns Auth response with tokens
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* ```typescript
|
|
546
|
+
* const response = await challengeHelper.createSuccessResponse(
|
|
547
|
+
* user,
|
|
548
|
+
* 'abc123',
|
|
549
|
+
* true,
|
|
550
|
+
* false
|
|
551
|
+
* );
|
|
552
|
+
* ```
|
|
553
|
+
*/
|
|
554
|
+
async createSuccessResponse(
|
|
555
|
+
user: IUser,
|
|
556
|
+
deviceToken?: string,
|
|
557
|
+
isTrusted?: boolean,
|
|
558
|
+
_isSocialLogin = false, // Reserved for future use
|
|
559
|
+
_metadata?: {
|
|
560
|
+
// Reserved for future use
|
|
561
|
+
gracePeriodEndsAt?: Date;
|
|
562
|
+
riskScore?: number;
|
|
563
|
+
riskLevel?: 'low' | 'medium' | 'high';
|
|
564
|
+
blockedUntil?: Date;
|
|
565
|
+
reason?: string;
|
|
566
|
+
},
|
|
567
|
+
): Promise<AuthResponseDTO> {
|
|
568
|
+
// Get client info from ClientInfoService (for deviceToken only - IP/userAgent come from context automatically)
|
|
569
|
+
const clientInfo = this.clientInfoService.get();
|
|
570
|
+
const finalDeviceToken = clientInfo.deviceToken || deviceToken;
|
|
571
|
+
|
|
572
|
+
// ============================================================================
|
|
573
|
+
// SECURITY: Defense-in-depth validation before token issuance
|
|
574
|
+
// ============================================================================
|
|
575
|
+
// Note: Challenge validation is now handled by state machine in determineAuthResponse
|
|
576
|
+
// This method is only called when state is AUTHENTICATED, so no additional check needed
|
|
577
|
+
|
|
578
|
+
// Generate token family for rotation tracking
|
|
579
|
+
const tokenFamily = this.jwtService.generateTokenFamily();
|
|
580
|
+
|
|
581
|
+
// Generate temporary tokens first (session creation requires token hashes)
|
|
582
|
+
// Note: deviceId not included in token - session.deviceId is source of truth
|
|
583
|
+
const tempTokens = await this.jwtService.generateTokenPair({
|
|
584
|
+
userId: user.sub, // Use sub in JWT payload (external identifier)
|
|
585
|
+
email: user.email,
|
|
586
|
+
sessionId: 'temp', // Temporary - will be regenerated with real sessionId
|
|
587
|
+
tokenFamily,
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// Generate deviceId if not provided
|
|
591
|
+
let finalDeviceId = finalDeviceToken;
|
|
592
|
+
if (!finalDeviceId) {
|
|
593
|
+
const crypto = await import('crypto');
|
|
594
|
+
finalDeviceId = crypto.randomUUID();
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
// Create session
|
|
598
|
+
// Client info (ipAddress, ipCountry, ipCity, userAgent) automatically extracted from ClientInfoService
|
|
599
|
+
const session = await this.sessionService.createSession({
|
|
600
|
+
userId: user.id, // Use internal id for foreign key
|
|
601
|
+
accessTokenHash: this.jwtService.hashToken(tempTokens.accessToken),
|
|
602
|
+
refreshTokenHash: this.jwtService.hashToken(tempTokens.refreshToken),
|
|
603
|
+
tokenFamily,
|
|
604
|
+
deviceId: finalDeviceId,
|
|
605
|
+
expiresAt: this.sessionService.getSessionExpirationDate(),
|
|
606
|
+
authMethod: 'password', // Default to password for challenge flows (signup, verification completion)
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
// Now regenerate tokens with the actual sessionId
|
|
610
|
+
// Note: deviceId not included in token - session.deviceId is source of truth
|
|
611
|
+
const tokens = await this.jwtService.generateTokenPair({
|
|
612
|
+
userId: user.sub,
|
|
613
|
+
email: user.email,
|
|
614
|
+
sessionId: session.id.toString(),
|
|
615
|
+
tokenFamily,
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// Update session with new token hashes
|
|
619
|
+
await this.sessionService.updateTokens(
|
|
620
|
+
session.id,
|
|
621
|
+
this.jwtService.hashToken(tokens.accessToken),
|
|
622
|
+
this.jwtService.hashToken(tokens.refreshToken),
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
// Decode tokens to get expiry times
|
|
626
|
+
const accessTokenValidation = await this.jwtService.validateAccessToken(tokens.accessToken);
|
|
627
|
+
const refreshTokenValidation = await this.jwtService.validateRefreshToken(tokens.refreshToken);
|
|
628
|
+
|
|
629
|
+
const response: AuthResponseDTO = {
|
|
630
|
+
accessToken: tokens.accessToken,
|
|
631
|
+
refreshToken: tokens.refreshToken,
|
|
632
|
+
accessTokenExpiresAt: accessTokenValidation.payload?.exp || 0,
|
|
633
|
+
refreshTokenExpiresAt: refreshTokenValidation.payload?.exp || 0,
|
|
634
|
+
trusted: isTrusted,
|
|
635
|
+
// Expose deviceToken so that:
|
|
636
|
+
// - In cookies mode, CookieTokenInterceptor can set the httpOnly nauth_device_token cookie
|
|
637
|
+
// - In JSON mode, mobile clients can store it securely and send via header
|
|
638
|
+
// NOTE: finalDeviceToken is a logical device identifier derived from:
|
|
639
|
+
// - clientInfo.deviceToken (existing trusted device), OR
|
|
640
|
+
// - deviceToken parameter passed from AuthService / state machine
|
|
641
|
+
deviceToken: finalDeviceToken,
|
|
642
|
+
user: {
|
|
643
|
+
sub: user.sub,
|
|
644
|
+
email: user.email,
|
|
645
|
+
firstName: user.firstName,
|
|
646
|
+
lastName: user.lastName,
|
|
647
|
+
phone: user.phone ?? undefined,
|
|
648
|
+
isEmailVerified: user.isEmailVerified,
|
|
649
|
+
isPhoneVerified: user.isPhoneVerified ?? undefined,
|
|
650
|
+
socialProviders: user.socialProviders ?? undefined,
|
|
651
|
+
hasPasswordHash: !!user.passwordHash,
|
|
652
|
+
},
|
|
653
|
+
userSub: user.sub,
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
return response;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Determine and create appropriate auth response
|
|
661
|
+
*
|
|
662
|
+
* Main entry point that decides whether to return challenges or tokens.
|
|
663
|
+
* Uses state machine to evaluate authentication flow state.
|
|
664
|
+
*
|
|
665
|
+
* @param params - Authentication parameters
|
|
666
|
+
* @param params.user - User attempting authentication
|
|
667
|
+
* @param params.config - Auth configuration
|
|
668
|
+
* @param params.deviceToken - Device token (optional)
|
|
669
|
+
* @param params.isSocialLogin - Whether this is a social login (OAuth) authentication (optional)
|
|
670
|
+
* @param params.skipMFAVerification - Skip MFA verification flag (optional)
|
|
671
|
+
* @param params.authProvider - Social auth provider name (optional)
|
|
672
|
+
* @returns Auth response (either challenge or success)
|
|
673
|
+
*
|
|
674
|
+
* @example
|
|
675
|
+
* ```typescript
|
|
676
|
+
* const response = await challengeHelper.determineAuthResponse({
|
|
677
|
+
* user,
|
|
678
|
+
* config,
|
|
679
|
+
* deviceToken: 'abc123',
|
|
680
|
+
* isSocialLogin: false
|
|
681
|
+
* });
|
|
682
|
+
* ```
|
|
683
|
+
*/
|
|
684
|
+
async determineAuthResponse(params: {
|
|
685
|
+
user: IUser;
|
|
686
|
+
config: NAuthConfig;
|
|
687
|
+
deviceToken?: string;
|
|
688
|
+
isSocialLogin?: boolean;
|
|
689
|
+
skipMFAVerification?: boolean;
|
|
690
|
+
authProvider?: string;
|
|
691
|
+
}): Promise<AuthResponseDTO> {
|
|
692
|
+
const { user, config, deviceToken, isSocialLogin = false, skipMFAVerification = false, authProvider } = params;
|
|
693
|
+
|
|
694
|
+
this.logger?.debug?.(
|
|
695
|
+
`[ChallengeHelper] determineAuthResponse called for user ${user.sub} (isSocialLogin=${isSocialLogin}, skipMFA=${skipMFAVerification}, deviceToken=${deviceToken ? 'present' : 'none'})`,
|
|
696
|
+
);
|
|
697
|
+
|
|
698
|
+
// Build context with pre-computed values
|
|
699
|
+
const context = await this.contextBuilder.build({
|
|
700
|
+
user,
|
|
701
|
+
config,
|
|
702
|
+
authMethod: isSocialLogin ? 'social' : 'password',
|
|
703
|
+
authProvider,
|
|
704
|
+
deviceToken,
|
|
705
|
+
skipMFAVerification,
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// Evaluate state using state machine
|
|
709
|
+
const state = await this.stateMachine.evaluateState(context);
|
|
710
|
+
|
|
711
|
+
// Get state definition
|
|
712
|
+
const stateDefinition = this.stateMachine.getStateDefinition(state);
|
|
713
|
+
if (!stateDefinition) {
|
|
714
|
+
this.logger?.error?.(`No state definition found for state: ${state}`, { state, userId: user.id });
|
|
715
|
+
throw new NAuthException(AuthErrorCode.INTERNAL_ERROR, 'Invalid authentication state');
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Build metadata if available
|
|
719
|
+
const metadata = this.stateMachine.buildMetadata(state, context);
|
|
720
|
+
|
|
721
|
+
// Convert state to response
|
|
722
|
+
const response = await this.stateToResponse(state, stateDefinition, context, metadata);
|
|
723
|
+
|
|
724
|
+
this.logger?.debug?.(
|
|
725
|
+
`[ChallengeHelper] State ${state} → Challenge: ${response.challengeName || 'SUCCESS'} for user ${user.sub}`,
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
return response;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Convert state to authentication response
|
|
733
|
+
*
|
|
734
|
+
* Maps state to appropriate response (challenge or success).
|
|
735
|
+
* Merges state metadata into response.
|
|
736
|
+
*
|
|
737
|
+
* @param state - Authentication flow state
|
|
738
|
+
* @param stateDefinition - State definition
|
|
739
|
+
* @param context - Authentication flow context
|
|
740
|
+
* @param metadata - Response metadata (optional)
|
|
741
|
+
* @returns Authentication response
|
|
742
|
+
*/
|
|
743
|
+
private async stateToResponse(
|
|
744
|
+
state: AuthFlowState,
|
|
745
|
+
stateDefinition: { challenge?: AuthChallenge },
|
|
746
|
+
context: AuthFlowContext,
|
|
747
|
+
metadata?: {
|
|
748
|
+
gracePeriodEndsAt?: Date;
|
|
749
|
+
riskScore?: number;
|
|
750
|
+
riskLevel?: 'low' | 'medium' | 'high';
|
|
751
|
+
blockedUntil?: Date;
|
|
752
|
+
reason?: string;
|
|
753
|
+
},
|
|
754
|
+
): Promise<AuthResponseDTO> {
|
|
755
|
+
// Get client info from ClientInfoService
|
|
756
|
+
const clientInfo = this.clientInfoService.get();
|
|
757
|
+
const deviceToken = clientInfo.deviceToken || context.deviceToken;
|
|
758
|
+
|
|
759
|
+
const authMethod = context.authMethod || 'password';
|
|
760
|
+
|
|
761
|
+
// Handle challenge states
|
|
762
|
+
if (stateDefinition.challenge) {
|
|
763
|
+
// Handle MFA_SETUP_REQUIRED challenge specially
|
|
764
|
+
if (stateDefinition.challenge === AuthChallenge.MFA_SETUP_REQUIRED) {
|
|
765
|
+
return this.createMFASetupChallengeResponse(context.user, context.config, authMethod, context.authProvider);
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// Handle MFA_REQUIRED challenge specially - needs preferred method logic
|
|
769
|
+
if (stateDefinition.challenge === AuthChallenge.MFA_REQUIRED) {
|
|
770
|
+
return this.createMFAChallengeResponse(context.user);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// Handle other challenges
|
|
774
|
+
return this.createChallengeResponse(
|
|
775
|
+
context.user,
|
|
776
|
+
stateDefinition.challenge,
|
|
777
|
+
context.config,
|
|
778
|
+
authMethod,
|
|
779
|
+
context.authProvider,
|
|
780
|
+
);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// Handle special states
|
|
784
|
+
if (state === AuthFlowState.GRACE_PERIOD_ACTIVE) {
|
|
785
|
+
// Grace period active - return success with metadata
|
|
786
|
+
const isTrusted = context.computed.isDeviceTrusted;
|
|
787
|
+
const response = await this.createSuccessResponse(
|
|
788
|
+
context.user,
|
|
789
|
+
deviceToken,
|
|
790
|
+
isTrusted,
|
|
791
|
+
context.authMethod === 'social',
|
|
792
|
+
metadata,
|
|
793
|
+
);
|
|
794
|
+
// Merge metadata
|
|
795
|
+
if (metadata?.gracePeriodEndsAt) {
|
|
796
|
+
(response as AuthResponseDTO & { gracePeriodEndsAt?: Date }).gracePeriodEndsAt = metadata.gracePeriodEndsAt;
|
|
797
|
+
}
|
|
798
|
+
if (metadata?.riskScore !== undefined) {
|
|
799
|
+
(response as AuthResponseDTO & { riskScore?: number }).riskScore = metadata.riskScore;
|
|
800
|
+
}
|
|
801
|
+
if (metadata?.riskLevel) {
|
|
802
|
+
(response as AuthResponseDTO & { riskLevel?: 'low' | 'medium' | 'high' }).riskLevel = metadata.riskLevel;
|
|
803
|
+
}
|
|
804
|
+
return response;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
if (state === AuthFlowState.BLOCKED) {
|
|
808
|
+
// User is blocked - throw exception with metadata
|
|
809
|
+
const errorCode =
|
|
810
|
+
(context.config.mfa?.adaptive?.blockedSignIn?.errorCode as AuthErrorCode) ||
|
|
811
|
+
AuthErrorCode.SIGNIN_BLOCKED_HIGH_RISK;
|
|
812
|
+
const message =
|
|
813
|
+
metadata?.reason ||
|
|
814
|
+
context.config.mfa?.adaptive?.blockedSignIn?.message ||
|
|
815
|
+
'Sign-in blocked due to suspicious activity';
|
|
816
|
+
throw new NAuthException(errorCode, message, {
|
|
817
|
+
expiresAt: metadata?.blockedUntil,
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
// AUTHENTICATED state - return success
|
|
822
|
+
const isTrusted = context.computed.isDeviceTrusted;
|
|
823
|
+
return this.createSuccessResponse(context.user, deviceToken, isTrusted, context.authMethod === 'social', metadata);
|
|
824
|
+
}
|
|
825
|
+
}
|