@jmlq/auth 0.0.1-alpha.1
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/README.md +306 -0
- package/dist/examples/bcrypt-password-hasher.example.d.ts +3 -0
- package/dist/examples/bcrypt-password-hasher.example.js +78 -0
- package/dist/examples/entity-object.example.d.ts +39 -0
- package/dist/examples/entity-object.example.js +411 -0
- package/dist/examples/factory-auth-service-example.d.ts +3 -0
- package/dist/examples/factory-auth-service-example.js +84 -0
- package/dist/examples/index.example.d.ts +12 -0
- package/dist/examples/index.example.js +171 -0
- package/dist/examples/jwt-algoritm.example.d.ts +47 -0
- package/dist/examples/jwt-algoritm.example.js +447 -0
- package/dist/examples/jwt-token-generator.example.d.ts +6 -0
- package/dist/examples/jwt-token-generator.example.js +49 -0
- package/dist/examples/jwt-verifier.example.d.ts +3 -0
- package/dist/examples/jwt-verifier.example.js +80 -0
- package/dist/examples/password-policy.example.d.ts +7 -0
- package/dist/examples/password-policy.example.js +57 -0
- package/dist/examples/service-jwt-token.example.d.ts +3 -0
- package/dist/examples/service-jwt-token.example.js +154 -0
- package/dist/examples/service-token-session.example.d.ts +3 -0
- package/dist/examples/service-token-session.example.js +139 -0
- package/dist/examples/use-case-login-with-password.example.d.ts +6 -0
- package/dist/examples/use-case-login-with-password.example.js +105 -0
- package/dist/examples/use-case-logout.example.d.ts +7 -0
- package/dist/examples/use-case-logout.example.js +134 -0
- package/dist/examples/use-case-refresh-token.example.d.ts +11 -0
- package/dist/examples/use-case-refresh-token.example.js +164 -0
- package/dist/examples/use-case-register-user.example.d.ts +9 -0
- package/dist/examples/use-case-register-user.example.js +110 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -0
- package/dist/src/application/dtos/index.d.ts +4 -0
- package/dist/src/application/dtos/index.js +20 -0
- package/dist/src/application/dtos/login.dto.d.ts +9 -0
- package/dist/src/application/dtos/login.dto.js +2 -0
- package/dist/src/application/dtos/logout.dto.d.ts +7 -0
- package/dist/src/application/dtos/logout.dto.js +2 -0
- package/dist/src/application/dtos/refresh-token.dto.d.ts +7 -0
- package/dist/src/application/dtos/refresh-token.dto.js +2 -0
- package/dist/src/application/dtos/register-user.dto.d.ts +16 -0
- package/dist/src/application/dtos/register-user.dto.js +2 -0
- package/dist/src/application/factories/auth-service.factory.d.ts +5 -0
- package/dist/src/application/factories/auth-service.factory.js +51 -0
- package/dist/src/application/factories/index.d.ts +1 -0
- package/dist/src/application/factories/index.js +17 -0
- package/dist/src/application/index.d.ts +3 -0
- package/dist/src/application/index.js +19 -0
- package/dist/src/application/use-cases/index.d.ts +4 -0
- package/dist/src/application/use-cases/index.js +20 -0
- package/dist/src/application/use-cases/login-with-password.use-case.d.ts +9 -0
- package/dist/src/application/use-cases/login-with-password.use-case.js +36 -0
- package/dist/src/application/use-cases/logout.use-case.d.ts +7 -0
- package/dist/src/application/use-cases/logout.use-case.js +22 -0
- package/dist/src/application/use-cases/refresh-token.use-case.d.ts +7 -0
- package/dist/src/application/use-cases/refresh-token.use-case.js +23 -0
- package/dist/src/application/use-cases/register-user.use-case.d.ts +10 -0
- package/dist/src/application/use-cases/register-user.use-case.js +37 -0
- package/dist/src/domain/entities/credential.entity.d.ts +78 -0
- package/dist/src/domain/entities/credential.entity.js +92 -0
- package/dist/src/domain/entities/index.d.ts +2 -0
- package/dist/src/domain/entities/index.js +18 -0
- package/dist/src/domain/entities/user.entity.d.ts +97 -0
- package/dist/src/domain/entities/user.entity.js +116 -0
- package/dist/src/domain/errors/auth-domain-error.d.ts +82 -0
- package/dist/src/domain/errors/auth-domain-error.js +112 -0
- package/dist/src/domain/errors/auth.errors.d.ts +56 -0
- package/dist/src/domain/errors/auth.errors.js +76 -0
- package/dist/src/domain/errors/identity.errors.d.ts +34 -0
- package/dist/src/domain/errors/identity.errors.js +82 -0
- package/dist/src/domain/errors/index.d.ts +2 -0
- package/dist/src/domain/errors/index.js +18 -0
- package/dist/src/domain/index.d.ts +6 -0
- package/dist/src/domain/index.js +22 -0
- package/dist/src/domain/object-values/email.d.ts +37 -0
- package/dist/src/domain/object-values/email.js +56 -0
- package/dist/src/domain/object-values/hashed-password.d.ts +28 -0
- package/dist/src/domain/object-values/hashed-password.js +73 -0
- package/dist/src/domain/object-values/id.d.ts +8 -0
- package/dist/src/domain/object-values/id.js +28 -0
- package/dist/src/domain/object-values/index.d.ts +5 -0
- package/dist/src/domain/object-values/index.js +13 -0
- package/dist/src/domain/object-values/permission.d.ts +15 -0
- package/dist/src/domain/object-values/permission.js +57 -0
- package/dist/src/domain/object-values/role.d.ts +25 -0
- package/dist/src/domain/object-values/role.js +108 -0
- package/dist/src/domain/ports/auth/password-hasher.d.ts +7 -0
- package/dist/src/domain/ports/auth/password-hasher.js +2 -0
- package/dist/src/domain/ports/auth/password-policy-config.port.d.ts +0 -0
- package/dist/src/domain/ports/auth/password-policy-config.port.js +10 -0
- package/dist/src/domain/ports/auth/password-policy.port.d.ts +10 -0
- package/dist/src/domain/ports/auth/password-policy.port.js +2 -0
- package/dist/src/domain/ports/config/auth-config.port.d.ts +19 -0
- package/dist/src/domain/ports/config/auth-config.port.js +3 -0
- package/dist/src/domain/ports/index.d.ts +9 -0
- package/dist/src/domain/ports/index.js +25 -0
- package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.d.ts +14 -0
- package/dist/src/domain/ports/jwt/factory/signature-strategy-factory.port.js +2 -0
- package/dist/src/domain/ports/jwt/payload/jwt-payload.port.d.ts +12 -0
- package/dist/src/domain/ports/jwt/payload/jwt-payload.port.js +2 -0
- package/dist/src/domain/ports/jwt/signature-strategy-factory.port.d.ts +14 -0
- package/dist/src/domain/ports/jwt/signature-strategy-factory.port.js +2 -0
- package/dist/src/domain/ports/jwt/signature-strategy.d.ts +30 -0
- package/dist/src/domain/ports/jwt/signature-strategy.js +4 -0
- package/dist/src/domain/ports/jwt/signature-strategy.port.d.ts +31 -0
- package/dist/src/domain/ports/jwt/signature-strategy.port.js +4 -0
- package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.d.ts +31 -0
- package/dist/src/domain/ports/jwt/strategy/signature-strategy.port.js +4 -0
- package/dist/src/domain/ports/repository/credential.repository.d.ts +10 -0
- package/dist/src/domain/ports/repository/credential.repository.js +2 -0
- package/dist/src/domain/ports/repository/index.d.ts +2 -0
- package/dist/src/domain/ports/repository/index.js +18 -0
- package/dist/src/domain/ports/repository/user.repository.d.ts +13 -0
- package/dist/src/domain/ports/repository/user.repository.js +2 -0
- package/dist/src/domain/ports/token/token-session.port.d.ts +7 -0
- package/dist/src/domain/ports/token/token-session.port.js +2 -0
- package/dist/src/domain/ports/token/token.service.port.d.ts +9 -0
- package/dist/src/domain/ports/token/token.service.port.js +2 -0
- package/dist/src/domain/props/create-payload-props.port.d.ts +0 -0
- package/dist/src/domain/props/create-payload-props.port.js +8 -0
- package/dist/src/domain/props/entities/credential.props.d.ts +8 -0
- package/dist/src/domain/props/entities/credential.props.js +2 -0
- package/dist/src/domain/props/entities/index.d.ts +2 -0
- package/dist/src/domain/props/entities/index.js +18 -0
- package/dist/src/domain/props/entities/user.props.d.ts +10 -0
- package/dist/src/domain/props/entities/user.props.js +2 -0
- package/dist/src/domain/props/index.d.ts +2 -0
- package/dist/src/domain/props/index.js +18 -0
- package/dist/src/domain/props/jwt/create-payload.props.d.ts +9 -0
- package/dist/src/domain/props/jwt/create-payload.props.js +2 -0
- package/dist/src/domain/props/jwt/generate-access-token.props.d.ts +8 -0
- package/dist/src/domain/props/jwt/generate-access-token.props.js +2 -0
- package/dist/src/domain/props/jwt/generate-refresh-token.props.d.ts +8 -0
- package/dist/src/domain/props/jwt/generate-refresh-token.props.js +2 -0
- package/dist/src/domain/props/jwt/generate-token.props.d.ts +10 -0
- package/dist/src/domain/props/jwt/generate-token.props.js +2 -0
- package/dist/src/domain/props/jwt/index.d.ts +5 -0
- package/dist/src/domain/props/jwt/index.js +21 -0
- package/dist/src/domain/props/jwt/jwt-subject.d.ts +7 -0
- package/dist/src/domain/props/jwt/jwt-subject.js +2 -0
- package/dist/src/domain/props/jwt/jwt-user.d.ts +7 -0
- package/dist/src/domain/props/jwt/jwt-user.js +2 -0
- package/dist/src/domain/props/services/generate-access-token.props.d.ts +8 -0
- package/dist/src/domain/props/services/generate-access-token.props.js +2 -0
- package/dist/src/domain/props/services/generate-refresh-token.props.d.ts +8 -0
- package/dist/src/domain/props/services/generate-refresh-token.props.js +2 -0
- package/dist/src/domain/props/services/index.d.ts +2 -0
- package/dist/src/domain/props/services/index.js +18 -0
- package/dist/src/domain/services/index.d.ts +1 -0
- package/dist/src/domain/services/index.js +17 -0
- package/dist/src/domain/services/password-policy.service.d.ts +8 -0
- package/dist/src/domain/services/password-policy.service.js +29 -0
- package/dist/src/domain/services/token.service.port.d.ts +9 -0
- package/dist/src/domain/services/token.service.port.js +2 -0
- package/dist/src/index.d.ts +78 -0
- package/dist/src/index.js +94 -0
- package/dist/src/infrastructure/index.d.ts +5 -0
- package/dist/src/infrastructure/index.js +21 -0
- package/dist/src/infrastructure/jwt/factory/index.d.ts +1 -0
- package/dist/src/infrastructure/jwt/factory/index.js +17 -0
- package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.d.ts +21 -0
- package/dist/src/infrastructure/jwt/factory/signature-strategy.factory.js +61 -0
- package/dist/src/infrastructure/jwt/index.d.ts +3 -0
- package/dist/src/infrastructure/jwt/index.js +19 -0
- package/dist/src/infrastructure/jwt/signature-strategy.factory.d.ts +21 -0
- package/dist/src/infrastructure/jwt/signature-strategy.factory.js +61 -0
- package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.d.ts +47 -0
- package/dist/src/infrastructure/jwt/strategies/ecdsa-signature-strategy.js +124 -0
- package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.d.ts +47 -0
- package/dist/src/infrastructure/jwt/strategies/ecdsa-signature.strategy.js +124 -0
- package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.d.ts +54 -0
- package/dist/src/infrastructure/jwt/strategies/hmac-signature-strategy.js +129 -0
- package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.d.ts +54 -0
- package/dist/src/infrastructure/jwt/strategies/hmac-signature.strategy.js +129 -0
- package/dist/src/infrastructure/jwt/strategies/index.d.ts +3 -0
- package/dist/src/infrastructure/jwt/strategies/index.js +19 -0
- package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.d.ts +47 -0
- package/dist/src/infrastructure/jwt/strategies/rsa-signature-strategy.js +124 -0
- package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.d.ts +47 -0
- package/dist/src/infrastructure/jwt/strategies/rsa-signature.strategy.js +124 -0
- package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.d.ts +57 -0
- package/dist/src/infrastructure/jwt/token/actions/jwt-token-generator.js +123 -0
- package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.d.ts +59 -0
- package/dist/src/infrastructure/jwt/token/actions/jwt-token-verifier.js +100 -0
- package/dist/src/infrastructure/jwt/token/index.d.ts +5 -0
- package/dist/src/infrastructure/jwt/token/index.js +21 -0
- package/dist/src/infrastructure/jwt/token/jwt-signer.d.ts +33 -0
- package/dist/src/infrastructure/jwt/token/jwt-signer.js +46 -0
- package/dist/src/infrastructure/jwt/token/jwt-token-parser.d.ts +29 -0
- package/dist/src/infrastructure/jwt/token/jwt-token-parser.js +57 -0
- package/dist/src/infrastructure/jwt/token/jwt-token-validator.d.ts +32 -0
- package/dist/src/infrastructure/jwt/token/jwt-token-validator.js +77 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-signer.d.ts +33 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-signer.js +46 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.d.ts +30 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-token-parser.js +57 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.d.ts +32 -0
- package/dist/src/infrastructure/jwt/token/tools/jwt-token-validator.js +77 -0
- package/dist/src/infrastructure/repositories/index.d.ts +1 -0
- package/dist/src/infrastructure/repositories/index.js +17 -0
- package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.d.ts +12 -0
- package/dist/src/infrastructure/repositories/test/in-memory-credential.repository.js +68 -0
- package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.d.ts +67 -0
- package/dist/src/infrastructure/repositories/test/in-memory-token-session.repository.js +128 -0
- package/dist/src/infrastructure/repositories/test/in-memory-user.repository.d.ts +11 -0
- package/dist/src/infrastructure/repositories/test/in-memory-user.repository.js +49 -0
- package/dist/src/infrastructure/repositories/test/index.d.ts +2 -0
- package/dist/src/infrastructure/repositories/test/index.js +18 -0
- package/dist/src/infrastructure/security/bcrypt-password-hasher.d.ts +6 -0
- package/dist/src/infrastructure/security/bcrypt-password-hasher.js +19 -0
- package/dist/src/infrastructure/security/index.d.ts +1 -0
- package/dist/src/infrastructure/security/index.js +17 -0
- package/dist/src/infrastructure/services/default-token-session.service.d.ts +18 -0
- package/dist/src/infrastructure/services/default-token-session.service.js +88 -0
- package/dist/src/infrastructure/services/index.d.ts +2 -0
- package/dist/src/infrastructure/services/index.js +18 -0
- package/dist/src/infrastructure/services/jwt-token.service.d.ts +15 -0
- package/dist/src/infrastructure/services/jwt-token.service.js +44 -0
- package/dist/src/infrastructure/services/simple-jwt-token.service.d.ts +15 -0
- package/dist/src/infrastructure/services/simple-jwt-token.service.js +46 -0
- package/dist/src/infrastructure/services/token-session.service.d.ts +24 -0
- package/dist/src/infrastructure/services/token-session.service.js +131 -0
- package/dist/src/infrastructure/types/auth-service-container.d.ts +14 -0
- package/dist/src/infrastructure/types/auth-service-container.js +2 -0
- package/dist/src/infrastructure/types/index.d.ts +1 -0
- package/dist/src/infrastructure/types/index.js +17 -0
- package/dist/src/shared/constants/index.d.ts +1 -0
- package/dist/src/shared/constants/index.js +17 -0
- package/dist/src/shared/constants/jwt-algorithms.d.ts +17 -0
- package/dist/src/shared/constants/jwt-algorithms.js +23 -0
- package/dist/src/shared/encoders/base64-url-encoder.d.ts +29 -0
- package/dist/src/shared/encoders/base64-url-encoder.js +45 -0
- package/dist/src/shared/encoders/index.d.ts +1 -0
- package/dist/src/shared/encoders/index.js +17 -0
- package/dist/src/shared/index.d.ts +4 -0
- package/dist/src/shared/index.js +20 -0
- package/dist/src/shared/types/index.d.ts +1 -0
- package/dist/src/shared/types/index.js +17 -0
- package/dist/src/shared/types/jwt.d.ts +25 -0
- package/dist/src/shared/types/jwt.js +2 -0
- package/dist/src/shared/types/jwt.types.d.ts +39 -0
- package/dist/src/shared/types/jwt.types.js +2 -0
- package/dist/src/shared/utils/index.d.ts +1 -0
- package/dist/src/shared/utils/index.js +17 -0
- package/dist/src/shared/utils/time-parser.d.ts +28 -0
- package/dist/src/shared/utils/time-parser.js +76 -0
- package/dist/tests/application/factory/auth-service-factory.spec.d.ts +1 -0
- package/dist/tests/application/factory/auth-service-factory.spec.js +97 -0
- package/dist/tests/application/use-cases/login-with-password.integration.spec.d.ts +1 -0
- package/dist/tests/application/use-cases/login-with-password.integration.spec.js +140 -0
- package/dist/tests/application/use-cases/logout-use-case.spec.d.ts +1 -0
- package/dist/tests/application/use-cases/logout-use-case.spec.js +40 -0
- package/dist/tests/application/use-cases/refresh-token-use-case.spec.d.ts +1 -0
- package/dist/tests/application/use-cases/refresh-token-use-case.spec.js +116 -0
- package/dist/tests/application/use-cases/register-user.usecase.spec.d.ts +1 -0
- package/dist/tests/application/use-cases/register-user.usecase.spec.js +151 -0
- package/dist/tests/domain/entities/credential.spec.d.ts +1 -0
- package/dist/tests/domain/entities/credential.spec.js +93 -0
- package/dist/tests/domain/entities/user.spec.d.ts +1 -0
- package/dist/tests/domain/entities/user.spec.js +93 -0
- package/dist/tests/domain/object-values/email.spec.d.ts +1 -0
- package/dist/tests/domain/object-values/email.spec.js +77 -0
- package/dist/tests/domain/object-values/hashed-password.spec.d.ts +1 -0
- package/dist/tests/domain/object-values/hashed-password.spec.js +54 -0
- package/dist/tests/domain/object-values/id.spec.d.ts +1 -0
- package/dist/tests/domain/object-values/id.spec.js +48 -0
- package/dist/tests/domain/object-values/permission.spec.d.ts +1 -0
- package/dist/tests/domain/object-values/permission.spec.js +75 -0
- package/dist/tests/domain/object-values/role.spec.d.ts +1 -0
- package/dist/tests/domain/object-values/role.spec.js +139 -0
- package/dist/tests/domain/services/default-password-policy.spec.d.ts +1 -0
- package/dist/tests/domain/services/default-password-policy.spec.js +69 -0
- package/dist/tests/doman/entities/credential.spec.d.ts +1 -0
- package/dist/tests/doman/entities/credential.spec.js +93 -0
- package/dist/tests/doman/entities/user.spec.d.ts +1 -0
- package/dist/tests/doman/entities/user.spec.js +93 -0
- package/dist/tests/doman/object-values/email.spec.d.ts +1 -0
- package/dist/tests/doman/object-values/email.spec.js +77 -0
- package/dist/tests/doman/object-values/hashed-password.spec.d.ts +1 -0
- package/dist/tests/doman/object-values/hashed-password.spec.js +54 -0
- package/dist/tests/doman/object-values/id.spec.d.ts +1 -0
- package/dist/tests/doman/object-values/id.spec.js +48 -0
- package/dist/tests/doman/object-values/permission.spec.d.ts +1 -0
- package/dist/tests/doman/object-values/permission.spec.js +75 -0
- package/dist/tests/doman/object-values/role.spec.d.ts +1 -0
- package/dist/tests/doman/object-values/role.spec.js +139 -0
- package/dist/tests/helpers/make-jwt-subject.d.ts +7 -0
- package/dist/tests/helpers/make-jwt-subject.js +16 -0
- package/dist/tests/helpers/make-jwt-user.d.ts +7 -0
- package/dist/tests/helpers/make-jwt-user.js +16 -0
- package/dist/tests/helpers/make-user.d.ts +2 -0
- package/dist/tests/helpers/make-user.js +15 -0
- package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/signature-strategy-factory.spec.js +127 -0
- package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/strategies/ecdsa-signature-strategy.spec.js +157 -0
- package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/strategies/hmac-signature-strategy.spec.js +150 -0
- package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/strategies/rsa-signature-strategy..spec.js +156 -0
- package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/actions/jwt-token-generator.spec.js +179 -0
- package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/actions/jwt-token-verifier.spec.js +142 -0
- package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/jwt-signer.spec.js +125 -0
- package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/jwt-token-parser.spec.js +116 -0
- package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/jwt-token-validator.spec.js +88 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-signer.spec.js +126 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-token-parser.spec.js +116 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.d.ts +1 -0
- package/dist/tests/infrastructure/jwt/token/tools/jwt-token-validator.spec.js +88 -0
- package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.d.ts +1 -0
- package/dist/tests/infrastructure/security/security/bcrypt-password-hasher.spec.js +37 -0
- package/dist/tests/infrastructure/services/jwt-token-service.spec.d.ts +1 -0
- package/dist/tests/infrastructure/services/jwt-token-service.spec.js +145 -0
- package/dist/tests/infrastructure/services/token-session.service.spec.d.ts +1 -0
- package/dist/tests/infrastructure/services/token-session.service.spec.js +269 -0
- package/dist/tests/shared/constants/jwt-algorithms.spec.d.ts +1 -0
- package/dist/tests/shared/constants/jwt-algorithms.spec.js +27 -0
- package/dist/tests/shared/encoders/base64-url-encoder.spec.d.ts +1 -0
- package/dist/tests/shared/encoders/base64-url-encoder.spec.js +70 -0
- package/dist/tests/shared/utils/time-parser.spec.d.ts +1 -0
- package/dist/tests/shared/utils/time-parser.spec.js +80 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +17 -0
- package/dist/utils/time-parser.d.ts +28 -0
- package/dist/utils/time-parser.js +76 -0
- package/package.json +48 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*Esta clase es el validador sintáctico del token JWT.
|
|
3
|
+
*Su función es detectar tokens mal formados o sospechosos antes de intentar decodificarlos.
|
|
4
|
+
*/
|
|
5
|
+
export declare class JwtTokenValidator {
|
|
6
|
+
/**
|
|
7
|
+
* Valida que el token JWT tenga un formato básico correcto.
|
|
8
|
+
* @param token El token JWT completo como string
|
|
9
|
+
* @throws InvalidTokenFormatError si el token no cumple con el formato básico JWT
|
|
10
|
+
*/
|
|
11
|
+
validateTokenInput(token: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* Comprueba lo más elemental sobre el formato del token JWT.
|
|
14
|
+
* @param token El token JWT completo como string
|
|
15
|
+
* @throws InvalidTokenFormatError si el token no cumple con los requisitos básicos
|
|
16
|
+
*/
|
|
17
|
+
private validateBasicFormat;
|
|
18
|
+
/**
|
|
19
|
+
* Se asegura de que tenga una estructura básica JWT:
|
|
20
|
+
* - Mínimo 10 caracteres
|
|
21
|
+
* - Contener exactamente dos puntos (.) separando header, payload y signature
|
|
22
|
+
* @param token El token JWT completo como string
|
|
23
|
+
* @throws InvalidTokenFormatError si la estructura no es válida
|
|
24
|
+
*/
|
|
25
|
+
private validateJwtStructure;
|
|
26
|
+
/**
|
|
27
|
+
* Verifica que el token solo contenga caracteres válidos Base64URL
|
|
28
|
+
* @param token El token JWT completo como string
|
|
29
|
+
* @throws InvalidTokenFormatError si se encuentran caracteres inválidos
|
|
30
|
+
*/
|
|
31
|
+
private validateCharacters;
|
|
32
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JwtTokenValidator = void 0;
|
|
4
|
+
const errors_1 = require("../../../../domain/errors");
|
|
5
|
+
/**
|
|
6
|
+
*Esta clase es el validador sintáctico del token JWT.
|
|
7
|
+
*Su función es detectar tokens mal formados o sospechosos antes de intentar decodificarlos.
|
|
8
|
+
*/
|
|
9
|
+
class JwtTokenValidator {
|
|
10
|
+
/**
|
|
11
|
+
* Valida que el token JWT tenga un formato básico correcto.
|
|
12
|
+
* @param token El token JWT completo como string
|
|
13
|
+
* @throws InvalidTokenFormatError si el token no cumple con el formato básico JWT
|
|
14
|
+
*/
|
|
15
|
+
validateTokenInput(token) {
|
|
16
|
+
this.validateBasicFormat(token);
|
|
17
|
+
this.validateJwtStructure(token);
|
|
18
|
+
this.validateCharacters(token);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Comprueba lo más elemental sobre el formato del token JWT.
|
|
22
|
+
* @param token El token JWT completo como string
|
|
23
|
+
* @throws InvalidTokenFormatError si el token no cumple con los requisitos básicos
|
|
24
|
+
*/
|
|
25
|
+
validateBasicFormat(token) {
|
|
26
|
+
// Null o undefined
|
|
27
|
+
if (token == null) {
|
|
28
|
+
throw new errors_1.InvalidTokenFormatError("Token cannot be null or undefined");
|
|
29
|
+
}
|
|
30
|
+
// Tipo de dato
|
|
31
|
+
if (typeof token !== "string") {
|
|
32
|
+
throw new errors_1.InvalidTokenFormatError(`Token must be a string, received: ${typeof token}`);
|
|
33
|
+
}
|
|
34
|
+
// Cadena vacía o con espacios en blanco
|
|
35
|
+
if (token.length === 0) {
|
|
36
|
+
throw new errors_1.InvalidTokenFormatError("Token cannot be empty");
|
|
37
|
+
}
|
|
38
|
+
// Solo espacios en blanco o con espacios al inicio/final
|
|
39
|
+
if (token.trim().length === 0) {
|
|
40
|
+
throw new errors_1.InvalidTokenFormatError("Token cannot be only whitespace");
|
|
41
|
+
}
|
|
42
|
+
// Espacios al inicio o al final
|
|
43
|
+
if (token !== token.trim()) {
|
|
44
|
+
throw new errors_1.InvalidTokenFormatError("Token cannot have leading or trailing whitespace");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Se asegura de que tenga una estructura básica JWT:
|
|
49
|
+
* - Mínimo 10 caracteres
|
|
50
|
+
* - Contener exactamente dos puntos (.) separando header, payload y signature
|
|
51
|
+
* @param token El token JWT completo como string
|
|
52
|
+
* @throws InvalidTokenFormatError si la estructura no es válida
|
|
53
|
+
*/
|
|
54
|
+
validateJwtStructure(token) {
|
|
55
|
+
// Mínimo viable: debe tener al menos 10 caracteres para ser un JWT válido
|
|
56
|
+
if (token.length < 10) {
|
|
57
|
+
throw new errors_1.InvalidTokenFormatError("Token is too short to be a valid JWT");
|
|
58
|
+
}
|
|
59
|
+
// Debe contener exactamente dos puntos (.) separando header, payload y signature
|
|
60
|
+
const dotCount = (token.match(/\./g) || []).length;
|
|
61
|
+
if (dotCount !== 2) {
|
|
62
|
+
throw new errors_1.InvalidTokenFormatError(`Invalid JWT format: expected 2 dots, found ${dotCount}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verifica que el token solo contenga caracteres válidos Base64URL
|
|
67
|
+
* @param token El token JWT completo como string
|
|
68
|
+
* @throws InvalidTokenFormatError si se encuentran caracteres inválidos
|
|
69
|
+
*/
|
|
70
|
+
validateCharacters(token) {
|
|
71
|
+
const base64UrlPattern = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;
|
|
72
|
+
if (!base64UrlPattern.test(token)) {
|
|
73
|
+
throw new errors_1.InvalidTokenFormatError("Token contains invalid characters for JWT format");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
exports.JwtTokenValidator = JwtTokenValidator;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./test";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./test"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Credential, ICredentialRepository, Id } from "../../../domain";
|
|
2
|
+
export declare class InMemoryCredentialRepository implements ICredentialRepository {
|
|
3
|
+
private credentials;
|
|
4
|
+
private refreshTokenIndex;
|
|
5
|
+
save(credential: Credential): Promise<void>;
|
|
6
|
+
findByUserId(userId: Id): Promise<Credential | null>;
|
|
7
|
+
findByRefreshToken(refreshToken: string): Promise<Credential | null>;
|
|
8
|
+
update(credential: Credential): Promise<void>;
|
|
9
|
+
delete(userId: Id): Promise<void>;
|
|
10
|
+
deleteByRefreshToken(refreshToken: string): Promise<void>;
|
|
11
|
+
clear(): void;
|
|
12
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryCredentialRepository = void 0;
|
|
4
|
+
// Esta clase es una implementación en memoria del repositorio de credenciales que sigue el patrón Repository de Domain-Driven Design (DDD). Su propósito principal es:
|
|
5
|
+
// Almacenar y gestionar credenciales de usuario en memoria durante la ejecución de la aplicación, principalmente para desarrollo, testing y prototipos.
|
|
6
|
+
class InMemoryCredentialRepository {
|
|
7
|
+
constructor() {
|
|
8
|
+
// Almacena las credenciales indexadas por el ID del usuario
|
|
9
|
+
this.credentials = new Map();
|
|
10
|
+
// Crea un índice inverso para buscar rápidamente por refresh token
|
|
11
|
+
this.refreshTokenIndex = new Map();
|
|
12
|
+
}
|
|
13
|
+
// Guarda una nueva credencial y actualiza el índice de refresh tokens
|
|
14
|
+
async save(credential) {
|
|
15
|
+
const key = credential.userId.getValue();
|
|
16
|
+
this.credentials.set(key, credential);
|
|
17
|
+
this.refreshTokenIndex.set(credential.refreshToken, key);
|
|
18
|
+
}
|
|
19
|
+
// Busca una credencial por ID de usuario
|
|
20
|
+
async findByUserId(userId) {
|
|
21
|
+
return this.credentials.get(userId.getValue()) || null;
|
|
22
|
+
}
|
|
23
|
+
// Busca una credencial por su refresh token
|
|
24
|
+
async findByRefreshToken(refreshToken) {
|
|
25
|
+
const userId = this.refreshTokenIndex.get(refreshToken);
|
|
26
|
+
if (!userId)
|
|
27
|
+
return null;
|
|
28
|
+
return this.credentials.get(userId) || null;
|
|
29
|
+
}
|
|
30
|
+
// Actualiza una credencial existente, limpiando el índice anterior
|
|
31
|
+
async update(credential) {
|
|
32
|
+
const key = credential.userId.getValue();
|
|
33
|
+
if (!this.credentials.has(key)) {
|
|
34
|
+
throw new Error("Credential not found");
|
|
35
|
+
}
|
|
36
|
+
// Limpiar el índice anterior
|
|
37
|
+
const oldCredential = this.credentials.get(key);
|
|
38
|
+
if (oldCredential) {
|
|
39
|
+
this.refreshTokenIndex.delete(oldCredential.refreshToken);
|
|
40
|
+
}
|
|
41
|
+
// Actualizar
|
|
42
|
+
this.credentials.set(key, credential);
|
|
43
|
+
this.refreshTokenIndex.set(credential.refreshToken, key);
|
|
44
|
+
}
|
|
45
|
+
// Elimina una credencial por ID de usuario
|
|
46
|
+
async delete(userId) {
|
|
47
|
+
const key = userId.getValue();
|
|
48
|
+
const credential = this.credentials.get(key);
|
|
49
|
+
if (credential) {
|
|
50
|
+
this.refreshTokenIndex.delete(credential.refreshToken);
|
|
51
|
+
}
|
|
52
|
+
this.credentials.delete(key);
|
|
53
|
+
}
|
|
54
|
+
// Elimina una credencial por su refresh token
|
|
55
|
+
async deleteByRefreshToken(refreshToken) {
|
|
56
|
+
const userId = this.refreshTokenIndex.get(refreshToken);
|
|
57
|
+
if (userId) {
|
|
58
|
+
this.credentials.delete(userId);
|
|
59
|
+
this.refreshTokenIndex.delete(refreshToken);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Método auxiliar para limpiar todos los datos (útil en tests)
|
|
63
|
+
clear() {
|
|
64
|
+
this.credentials.clear();
|
|
65
|
+
this.refreshTokenIndex.clear();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.InMemoryCredentialRepository = InMemoryCredentialRepository;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ITokenSession, Credential, User } from "../../../domain";
|
|
2
|
+
/**
|
|
3
|
+
* Implementación de ITokenSession pensada como infraestructura sencilla
|
|
4
|
+
* para el ejemplo. En una app real esto sería un adaptador a Redis, BD, etc.
|
|
5
|
+
*/
|
|
6
|
+
export declare class InMemoryTokenSessionRepository implements ITokenSession {
|
|
7
|
+
/**
|
|
8
|
+
* Store principal de sesiones activas indexadas por refreshToken.
|
|
9
|
+
* Guardamos tanto la Credential como el User para poder cumplir con
|
|
10
|
+
* validateSession(accessToken): Promise<User | null>.
|
|
11
|
+
*/
|
|
12
|
+
private readonly sessionsByRefreshToken;
|
|
13
|
+
/**
|
|
14
|
+
* Índice auxiliar por accessToken para validaciones rápidas.
|
|
15
|
+
*/
|
|
16
|
+
private readonly sessionsByAccessToken;
|
|
17
|
+
/**
|
|
18
|
+
* TTL del access token en milisegundos.
|
|
19
|
+
* (En un sistema real vendría de la config de Auth/JWT).
|
|
20
|
+
*/
|
|
21
|
+
private readonly accessTokenTtlMs;
|
|
22
|
+
/**
|
|
23
|
+
* TTL del refresh token en milisegundos.
|
|
24
|
+
* (Aquí se usa solo de referencia para ejemplo).
|
|
25
|
+
*/
|
|
26
|
+
private readonly refreshTokenTtlMs;
|
|
27
|
+
constructor(options?: {
|
|
28
|
+
accessTokenTtlMs?: number;
|
|
29
|
+
refreshTokenTtlMs?: number;
|
|
30
|
+
initialSessions?: {
|
|
31
|
+
credential: Credential;
|
|
32
|
+
user: User;
|
|
33
|
+
}[];
|
|
34
|
+
});
|
|
35
|
+
/**
|
|
36
|
+
* Crea una nueva sesión para el usuario:
|
|
37
|
+
* - Genera accessToken y refreshToken aleatorios.
|
|
38
|
+
* - Calcula fecha de expiración del accessToken.
|
|
39
|
+
* - Crea una Credential y la almacena en memoria.
|
|
40
|
+
*/
|
|
41
|
+
createSession(user: User): Promise<Credential>;
|
|
42
|
+
/**
|
|
43
|
+
* Refresca una sesión a partir del refreshToken:
|
|
44
|
+
* - Verifica que exista una sesión asociada.
|
|
45
|
+
* - Genera nuevos tokens y devuelve una nueva Credential.
|
|
46
|
+
* - Actualiza los índices in-memory.
|
|
47
|
+
*/
|
|
48
|
+
refreshSession(refreshToken: string): Promise<Credential>;
|
|
49
|
+
/**
|
|
50
|
+
* Valida una sesión a partir del accessToken:
|
|
51
|
+
* - Verifica que exista.
|
|
52
|
+
* - Revisa si el accessToken está expirado.
|
|
53
|
+
* - Devuelve el User asociado o null si no es válido.
|
|
54
|
+
*/
|
|
55
|
+
validateSession(accessToken: string): Promise<User | null>;
|
|
56
|
+
/**
|
|
57
|
+
* Revoca una sesión eliminando el refreshToken de la store.
|
|
58
|
+
* Si no existe, lanza un error genérico que luego el caso de uso
|
|
59
|
+
* puede envolver en LogoutError.
|
|
60
|
+
*/
|
|
61
|
+
revokeSession(refreshToken: string): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Helper para generar tokens pseudo-aleatorios.
|
|
64
|
+
* En producción usarías JWTs firmados, no simples random strings.
|
|
65
|
+
*/
|
|
66
|
+
private generateToken;
|
|
67
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryTokenSessionRepository = void 0;
|
|
4
|
+
// src/infrastructure/repositories/in-memory-token-session.repository.ts
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
const domain_1 = require("../../../domain");
|
|
7
|
+
/**
|
|
8
|
+
* Implementación de ITokenSession pensada como infraestructura sencilla
|
|
9
|
+
* para el ejemplo. En una app real esto sería un adaptador a Redis, BD, etc.
|
|
10
|
+
*/
|
|
11
|
+
class InMemoryTokenSessionRepository {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
/**
|
|
14
|
+
* Store principal de sesiones activas indexadas por refreshToken.
|
|
15
|
+
* Guardamos tanto la Credential como el User para poder cumplir con
|
|
16
|
+
* validateSession(accessToken): Promise<User | null>.
|
|
17
|
+
*/
|
|
18
|
+
this.sessionsByRefreshToken = new Map();
|
|
19
|
+
/**
|
|
20
|
+
* Índice auxiliar por accessToken para validaciones rápidas.
|
|
21
|
+
*/
|
|
22
|
+
this.sessionsByAccessToken = new Map();
|
|
23
|
+
this.accessTokenTtlMs = options?.accessTokenTtlMs ?? 15 * 60 * 1000; // 15 minutos
|
|
24
|
+
this.refreshTokenTtlMs =
|
|
25
|
+
options?.refreshTokenTtlMs ?? 7 * 24 * 60 * 60 * 1000; // 7 días
|
|
26
|
+
if (options?.initialSessions) {
|
|
27
|
+
for (const record of options.initialSessions) {
|
|
28
|
+
this.sessionsByRefreshToken.set(record.credential.refreshToken, record);
|
|
29
|
+
this.sessionsByAccessToken.set(record.credential.accessToken, record);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Crea una nueva sesión para el usuario:
|
|
35
|
+
* - Genera accessToken y refreshToken aleatorios.
|
|
36
|
+
* - Calcula fecha de expiración del accessToken.
|
|
37
|
+
* - Crea una Credential y la almacena en memoria.
|
|
38
|
+
*/
|
|
39
|
+
async createSession(user) {
|
|
40
|
+
const now = new Date();
|
|
41
|
+
const accessToken = this.generateToken("at");
|
|
42
|
+
const refreshToken = this.generateToken("rt");
|
|
43
|
+
const expiresAt = new Date(now.getTime() + this.accessTokenTtlMs);
|
|
44
|
+
const credential = new domain_1.Credential({
|
|
45
|
+
userId: user.id, // ajusta si tu VO de Id se instancia diferente
|
|
46
|
+
accessToken,
|
|
47
|
+
refreshToken,
|
|
48
|
+
expiresAt,
|
|
49
|
+
createdAt: now,
|
|
50
|
+
});
|
|
51
|
+
const record = { credential, user };
|
|
52
|
+
this.sessionsByRefreshToken.set(refreshToken, record);
|
|
53
|
+
this.sessionsByAccessToken.set(accessToken, record);
|
|
54
|
+
return credential;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Refresca una sesión a partir del refreshToken:
|
|
58
|
+
* - Verifica que exista una sesión asociada.
|
|
59
|
+
* - Genera nuevos tokens y devuelve una nueva Credential.
|
|
60
|
+
* - Actualiza los índices in-memory.
|
|
61
|
+
*/
|
|
62
|
+
async refreshSession(refreshToken) {
|
|
63
|
+
const record = this.sessionsByRefreshToken.get(refreshToken);
|
|
64
|
+
if (!record) {
|
|
65
|
+
throw new Error("Refresh token not found");
|
|
66
|
+
}
|
|
67
|
+
// Eliminamos la sesión anterior
|
|
68
|
+
this.sessionsByRefreshToken.delete(record.credential.refreshToken);
|
|
69
|
+
this.sessionsByAccessToken.delete(record.credential.accessToken);
|
|
70
|
+
// Creamos una nueva sesión para el mismo usuario
|
|
71
|
+
const now = new Date();
|
|
72
|
+
const newAccessToken = this.generateToken("at");
|
|
73
|
+
const newRefreshToken = this.generateToken("rt");
|
|
74
|
+
const newExpiresAt = new Date(now.getTime() + this.accessTokenTtlMs);
|
|
75
|
+
const newCredential = new domain_1.Credential({
|
|
76
|
+
userId: record.user.id,
|
|
77
|
+
accessToken: newAccessToken,
|
|
78
|
+
refreshToken: newRefreshToken,
|
|
79
|
+
expiresAt: newExpiresAt,
|
|
80
|
+
createdAt: now,
|
|
81
|
+
});
|
|
82
|
+
const newRecord = { credential: newCredential, user: record.user };
|
|
83
|
+
this.sessionsByRefreshToken.set(newRefreshToken, newRecord);
|
|
84
|
+
this.sessionsByAccessToken.set(newAccessToken, newRecord);
|
|
85
|
+
return newCredential;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Valida una sesión a partir del accessToken:
|
|
89
|
+
* - Verifica que exista.
|
|
90
|
+
* - Revisa si el accessToken está expirado.
|
|
91
|
+
* - Devuelve el User asociado o null si no es válido.
|
|
92
|
+
*/
|
|
93
|
+
async validateSession(accessToken) {
|
|
94
|
+
const record = this.sessionsByAccessToken.get(accessToken);
|
|
95
|
+
if (!record) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
const now = Date.now();
|
|
99
|
+
if (record.credential.expiresAt.getTime() <= now) {
|
|
100
|
+
// Limpieza agresiva de sesión expirada
|
|
101
|
+
this.sessionsByAccessToken.delete(record.credential.accessToken);
|
|
102
|
+
this.sessionsByRefreshToken.delete(record.credential.refreshToken);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
return record.user;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Revoca una sesión eliminando el refreshToken de la store.
|
|
109
|
+
* Si no existe, lanza un error genérico que luego el caso de uso
|
|
110
|
+
* puede envolver en LogoutError.
|
|
111
|
+
*/
|
|
112
|
+
async revokeSession(refreshToken) {
|
|
113
|
+
const record = this.sessionsByRefreshToken.get(refreshToken);
|
|
114
|
+
if (!record) {
|
|
115
|
+
throw new Error("Refresh token not found or already revoked");
|
|
116
|
+
}
|
|
117
|
+
this.sessionsByRefreshToken.delete(refreshToken);
|
|
118
|
+
this.sessionsByAccessToken.delete(record.credential.accessToken);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Helper para generar tokens pseudo-aleatorios.
|
|
122
|
+
* En producción usarías JWTs firmados, no simples random strings.
|
|
123
|
+
*/
|
|
124
|
+
generateToken(prefix) {
|
|
125
|
+
return `${prefix}.${(0, crypto_1.randomBytes)(24).toString("hex")}`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
exports.InMemoryTokenSessionRepository = InMemoryTokenSessionRepository;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Email, Id, IUserRepository, User } from "../../../domain";
|
|
2
|
+
export declare class InMemoryUserRepository implements IUserRepository {
|
|
3
|
+
private users;
|
|
4
|
+
save(user: User): Promise<void>;
|
|
5
|
+
findById(id: Id): Promise<User | null>;
|
|
6
|
+
findByEmail(email: Email): Promise<User | null>;
|
|
7
|
+
update(user: User): Promise<void>;
|
|
8
|
+
delete(id: Id): Promise<void>;
|
|
9
|
+
exists(email: Email): Promise<boolean>;
|
|
10
|
+
clear(): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InMemoryUserRepository = void 0;
|
|
4
|
+
// Esta clase es una implementación en memoria del repositorio de usuarios que gestiona la persistencia de entidades User durante la ejecución de la aplicación.
|
|
5
|
+
// Función principal: Almacenar y gestionar usuarios en memoria, proporcionando operaciones CRUD completas para la entidad User.
|
|
6
|
+
class InMemoryUserRepository {
|
|
7
|
+
constructor() {
|
|
8
|
+
// almacena los usuarios indexados por su ID único
|
|
9
|
+
this.users = new Map();
|
|
10
|
+
}
|
|
11
|
+
// Guarda un nuevo usuario en el repositorio
|
|
12
|
+
async save(user) {
|
|
13
|
+
this.users.set(user.id.getValue(), user);
|
|
14
|
+
}
|
|
15
|
+
// Busca un usuario por su ID único
|
|
16
|
+
async findById(id) {
|
|
17
|
+
return this.users.get(id.getValue()) || null;
|
|
18
|
+
}
|
|
19
|
+
// Busca un usuario por su dirección de email
|
|
20
|
+
async findByEmail(email) {
|
|
21
|
+
for (const user of this.users.values()) {
|
|
22
|
+
if (user.email.equals(email)) {
|
|
23
|
+
return user;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
// Actualiza un usuario existente
|
|
29
|
+
async update(user) {
|
|
30
|
+
if (!this.users.has(user.id.getValue())) {
|
|
31
|
+
throw new Error("User not found");
|
|
32
|
+
}
|
|
33
|
+
this.users.set(user.id.getValue(), user);
|
|
34
|
+
}
|
|
35
|
+
// Elimina un usuario por su ID
|
|
36
|
+
async delete(id) {
|
|
37
|
+
this.users.delete(id.getValue());
|
|
38
|
+
}
|
|
39
|
+
// Verifica si existe un usuario con el email dado
|
|
40
|
+
async exists(email) {
|
|
41
|
+
const user = await this.findByEmail(email);
|
|
42
|
+
return user !== null;
|
|
43
|
+
}
|
|
44
|
+
// Método auxiliar para limpiar todos los datos
|
|
45
|
+
clear() {
|
|
46
|
+
this.users.clear();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.InMemoryUserRepository = InMemoryUserRepository;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./in-memory-credential.repository"), exports);
|
|
18
|
+
__exportStar(require("./in-memory-user.repository"), exports);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { IPasswordHasher } from "../../domain/ports";
|
|
2
|
+
export declare class BcryptPasswordHasher implements IPasswordHasher {
|
|
3
|
+
private readonly saltRounds;
|
|
4
|
+
hash(password: string): Promise<string>;
|
|
5
|
+
compare(plainPassword: string, hashedPassword: string): Promise<boolean>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BcryptPasswordHasher = void 0;
|
|
7
|
+
const bcryptjs_1 = __importDefault(require("bcryptjs"));
|
|
8
|
+
class BcryptPasswordHasher {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.saltRounds = 10;
|
|
11
|
+
}
|
|
12
|
+
async hash(password) {
|
|
13
|
+
return bcryptjs_1.default.hash(password, this.saltRounds);
|
|
14
|
+
}
|
|
15
|
+
async compare(plainPassword, hashedPassword) {
|
|
16
|
+
return bcryptjs_1.default.compare(plainPassword, hashedPassword);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.BcryptPasswordHasher = BcryptPasswordHasher;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./bcrypt-password-hasher";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./bcrypt-password-hasher"), exports);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Credential, ICredentialRepository, ITokenService, ITokenSession, IUserRepository, User } from "../../domain";
|
|
2
|
+
export declare class DefaultTokenSessionService implements ITokenSession {
|
|
3
|
+
private readonly tokenService;
|
|
4
|
+
private readonly userRepository;
|
|
5
|
+
private readonly credentialRepository;
|
|
6
|
+
private readonly accessTokenExpiration;
|
|
7
|
+
private readonly refreshTokenExpiration;
|
|
8
|
+
private readonly accessTokenSecret?;
|
|
9
|
+
private readonly refreshTokenSecret?;
|
|
10
|
+
private readonly accessMs;
|
|
11
|
+
private readonly refreshMs;
|
|
12
|
+
constructor(tokenService: ITokenService, userRepository: IUserRepository, credentialRepository: ICredentialRepository, accessTokenExpiration?: string, refreshTokenExpiration?: string, accessTokenSecret?: string | undefined, refreshTokenSecret?: string | undefined);
|
|
13
|
+
private buildJwtConfig;
|
|
14
|
+
createSession(user: User): Promise<Credential>;
|
|
15
|
+
refreshSession(refreshToken: string): Promise<Credential>;
|
|
16
|
+
validateSession(accessToken: string): Promise<User | null>;
|
|
17
|
+
revokeSession(refreshToken: string): Promise<void>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultTokenSessionService = void 0;
|
|
4
|
+
const domain_1 = require("../../domain");
|
|
5
|
+
const shared_1 = require("../../shared");
|
|
6
|
+
class DefaultTokenSessionService {
|
|
7
|
+
constructor(tokenService, userRepository, credentialRepository, accessTokenExpiration = "15m", refreshTokenExpiration = "7d", accessTokenSecret, refreshTokenSecret) {
|
|
8
|
+
this.tokenService = tokenService;
|
|
9
|
+
this.userRepository = userRepository;
|
|
10
|
+
this.credentialRepository = credentialRepository;
|
|
11
|
+
this.accessTokenExpiration = accessTokenExpiration;
|
|
12
|
+
this.refreshTokenExpiration = refreshTokenExpiration;
|
|
13
|
+
this.accessTokenSecret = accessTokenSecret;
|
|
14
|
+
this.refreshTokenSecret = refreshTokenSecret;
|
|
15
|
+
try {
|
|
16
|
+
this.accessMs = shared_1.TimeParser.parseToMilliseconds(accessTokenExpiration);
|
|
17
|
+
this.refreshMs = shared_1.TimeParser.parseToMilliseconds(refreshTokenExpiration);
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
throw new Error(`Invalid token expiration configuration: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
buildJwtConfig() {
|
|
24
|
+
return {
|
|
25
|
+
accessTokenExpirationMs: this.accessMs,
|
|
26
|
+
refreshTokenExpirationMs: this.refreshMs,
|
|
27
|
+
accessTokenSecret: this.accessTokenSecret,
|
|
28
|
+
refreshTokenSecret: this.refreshTokenSecret,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async createSession(user) {
|
|
32
|
+
const config = this.buildJwtConfig();
|
|
33
|
+
const accessToken = await this.tokenService.generateAccessToken({
|
|
34
|
+
user: {
|
|
35
|
+
id: user.id.toString(),
|
|
36
|
+
email: user.email.toString(),
|
|
37
|
+
roles: user.roles.map((role) => role.getValuePublic()),
|
|
38
|
+
},
|
|
39
|
+
expiresIn: this.accessTokenExpiration,
|
|
40
|
+
config,
|
|
41
|
+
});
|
|
42
|
+
const refreshToken = await this.tokenService.generateRefreshToken({
|
|
43
|
+
user: {
|
|
44
|
+
id: user.id.toString(),
|
|
45
|
+
email: user.email.toString(),
|
|
46
|
+
roles: user.roles.map((role) => role.getValuePublic()),
|
|
47
|
+
},
|
|
48
|
+
expiresIn: this.refreshTokenExpiration,
|
|
49
|
+
config,
|
|
50
|
+
});
|
|
51
|
+
const credential = domain_1.Credential.create(user.id, accessToken, refreshToken, new Date(Date.now() + this.accessMs));
|
|
52
|
+
await this.credentialRepository.save(credential);
|
|
53
|
+
return credential;
|
|
54
|
+
}
|
|
55
|
+
async refreshSession(refreshToken) {
|
|
56
|
+
const existing = await this.credentialRepository.findByRefreshToken(refreshToken);
|
|
57
|
+
if (!existing) {
|
|
58
|
+
throw new domain_1.InvalidOrExpiredRefreshTokenError();
|
|
59
|
+
}
|
|
60
|
+
const payload = await this.tokenService
|
|
61
|
+
.verifyRefreshToken(refreshToken)
|
|
62
|
+
.catch(() => {
|
|
63
|
+
throw new domain_1.InvalidOrExpiredRefreshTokenError();
|
|
64
|
+
});
|
|
65
|
+
const user = await this.userRepository.findById(new domain_1.Id(payload.sub));
|
|
66
|
+
if (!user)
|
|
67
|
+
throw new domain_1.UserNotFoundError();
|
|
68
|
+
if (!user.canLogin())
|
|
69
|
+
throw new domain_1.UserDisabledError();
|
|
70
|
+
const newCredential = await this.createSession(user);
|
|
71
|
+
await this.credentialRepository.deleteByRefreshToken(refreshToken); // rotación
|
|
72
|
+
return newCredential;
|
|
73
|
+
}
|
|
74
|
+
async validateSession(accessToken) {
|
|
75
|
+
try {
|
|
76
|
+
const payload = await this.tokenService.verifyAccessToken(accessToken);
|
|
77
|
+
const user = await this.userRepository.findById(new domain_1.Id(payload.sub));
|
|
78
|
+
return user && user.canLogin() ? user : null;
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async revokeSession(refreshToken) {
|
|
85
|
+
await this.credentialRepository.deleteByRefreshToken(refreshToken);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.DefaultTokenSessionService = DefaultTokenSessionService;
|