@twin.org/api-auth-entity-storage-service 0.0.3-next.4 → 0.0.3-next.40

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.
Files changed (104) hide show
  1. package/README.md +2 -2
  2. package/dist/es/entities/authenticationAuditEntry.js +101 -0
  3. package/dist/es/entities/authenticationAuditEntry.js.map +1 -0
  4. package/dist/es/entities/authenticationRateEntry.js +37 -0
  5. package/dist/es/entities/authenticationRateEntry.js.map +1 -0
  6. package/dist/es/entities/authenticationUser.js +17 -1
  7. package/dist/es/entities/authenticationUser.js.map +1 -1
  8. package/dist/es/index.js +11 -1
  9. package/dist/es/index.js.map +1 -1
  10. package/dist/es/models/IAuthHeaderProcessorConstructorOptions.js.map +1 -1
  11. package/dist/es/models/IEntityStorageAuthenticationAdminServiceConstructorOptions.js.map +1 -1
  12. package/dist/es/models/IEntityStorageAuthenticationAuditServiceConfig.js +4 -0
  13. package/dist/es/models/IEntityStorageAuthenticationAuditServiceConfig.js.map +1 -0
  14. package/dist/es/models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js +2 -0
  15. package/dist/es/models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js.map +1 -0
  16. package/dist/es/models/IEntityStorageAuthenticationRateServiceConfig.js +2 -0
  17. package/dist/es/models/IEntityStorageAuthenticationRateServiceConfig.js.map +1 -0
  18. package/dist/es/models/IEntityStorageAuthenticationRateServiceConstructorOptions.js +2 -0
  19. package/dist/es/models/IEntityStorageAuthenticationRateServiceConstructorOptions.js.map +1 -0
  20. package/dist/es/models/IEntityStorageAuthenticationServiceConfig.js +0 -2
  21. package/dist/es/models/IEntityStorageAuthenticationServiceConfig.js.map +1 -1
  22. package/dist/es/models/IEntityStorageAuthenticationServiceConstructorOptions.js.map +1 -1
  23. package/dist/es/processors/authHeaderProcessor.js +62 -10
  24. package/dist/es/processors/authHeaderProcessor.js.map +1 -1
  25. package/dist/es/restEntryPoints.js +14 -0
  26. package/dist/es/restEntryPoints.js.map +1 -1
  27. package/dist/es/routes/entityStorageAuthenticationAdminRoutes.js +362 -0
  28. package/dist/es/routes/entityStorageAuthenticationAdminRoutes.js.map +1 -0
  29. package/dist/es/routes/entityStorageAuthenticationAuditRoutes.js +174 -0
  30. package/dist/es/routes/entityStorageAuthenticationAuditRoutes.js.map +1 -0
  31. package/dist/es/routes/entityStorageAuthenticationRoutes.js +20 -21
  32. package/dist/es/routes/entityStorageAuthenticationRoutes.js.map +1 -1
  33. package/dist/es/schema.js +4 -0
  34. package/dist/es/schema.js.map +1 -1
  35. package/dist/es/services/entityStorageAuthenticationAdminService.js +161 -55
  36. package/dist/es/services/entityStorageAuthenticationAdminService.js.map +1 -1
  37. package/dist/es/services/entityStorageAuthenticationAuditService.js +178 -0
  38. package/dist/es/services/entityStorageAuthenticationAuditService.js.map +1 -0
  39. package/dist/es/services/entityStorageAuthenticationRateService.js +202 -0
  40. package/dist/es/services/entityStorageAuthenticationRateService.js.map +1 -0
  41. package/dist/es/services/entityStorageAuthenticationService.js +200 -14
  42. package/dist/es/services/entityStorageAuthenticationService.js.map +1 -1
  43. package/dist/es/utils/passwordHelper.js +45 -16
  44. package/dist/es/utils/passwordHelper.js.map +1 -1
  45. package/dist/es/utils/tokenHelper.js +45 -21
  46. package/dist/es/utils/tokenHelper.js.map +1 -1
  47. package/dist/types/entities/authenticationAuditEntry.d.ts +49 -0
  48. package/dist/types/entities/authenticationRateEntry.d.ts +17 -0
  49. package/dist/types/entities/authenticationUser.d.ts +8 -0
  50. package/dist/types/index.d.ts +11 -1
  51. package/dist/types/models/IAuthHeaderProcessorConstructorOptions.d.ts +14 -0
  52. package/dist/types/models/IEntityStorageAuthenticationAdminServiceConstructorOptions.d.ts +5 -0
  53. package/dist/types/models/IEntityStorageAuthenticationAuditServiceConfig.d.ts +9 -0
  54. package/dist/types/models/IEntityStorageAuthenticationAuditServiceConstructorOptions.d.ts +15 -0
  55. package/dist/types/models/IEntityStorageAuthenticationRateServiceConfig.d.ts +10 -0
  56. package/dist/types/models/IEntityStorageAuthenticationRateServiceConstructorOptions.d.ts +20 -0
  57. package/dist/types/models/IEntityStorageAuthenticationServiceConfig.d.ts +22 -1
  58. package/dist/types/models/IEntityStorageAuthenticationServiceConstructorOptions.d.ts +17 -3
  59. package/dist/types/processors/authHeaderProcessor.d.ts +1 -1
  60. package/dist/types/routes/entityStorageAuthenticationAdminRoutes.d.ts +61 -0
  61. package/dist/types/routes/entityStorageAuthenticationAuditRoutes.d.ts +29 -0
  62. package/dist/types/services/entityStorageAuthenticationAdminService.d.ts +23 -6
  63. package/dist/types/services/entityStorageAuthenticationAuditService.d.ts +59 -0
  64. package/dist/types/services/entityStorageAuthenticationRateService.d.ts +60 -0
  65. package/dist/types/services/entityStorageAuthenticationService.d.ts +8 -3
  66. package/dist/types/utils/passwordHelper.d.ts +13 -5
  67. package/dist/types/utils/tokenHelper.d.ts +9 -2
  68. package/docs/changelog.md +658 -64
  69. package/docs/examples.md +178 -1
  70. package/docs/reference/classes/AuthHeaderProcessor.md +10 -10
  71. package/docs/reference/classes/AuthenticationAuditEntry.md +101 -0
  72. package/docs/reference/classes/AuthenticationRateEntry.md +37 -0
  73. package/docs/reference/classes/AuthenticationUser.md +21 -5
  74. package/docs/reference/classes/EntityStorageAuthenticationAdminService.md +78 -18
  75. package/docs/reference/classes/EntityStorageAuthenticationAuditService.md +157 -0
  76. package/docs/reference/classes/EntityStorageAuthenticationRateService.md +227 -0
  77. package/docs/reference/classes/EntityStorageAuthenticationService.md +36 -16
  78. package/docs/reference/classes/PasswordHelper.md +37 -12
  79. package/docs/reference/classes/TokenHelper.md +44 -8
  80. package/docs/reference/functions/authenticationAdminCreateUser.md +31 -0
  81. package/docs/reference/functions/authenticationAdminGetUser.md +31 -0
  82. package/docs/reference/functions/authenticationAdminGetUserByIdentity.md +31 -0
  83. package/docs/reference/functions/authenticationAdminRemoveUser.md +31 -0
  84. package/docs/reference/functions/authenticationAdminUpdateUser.md +31 -0
  85. package/docs/reference/functions/authenticationAdminUpdateUserPassword.md +31 -0
  86. package/docs/reference/functions/authenticationAuditCreate.md +31 -0
  87. package/docs/reference/functions/authenticationAuditQuery.md +31 -0
  88. package/docs/reference/functions/generateRestRoutesAuthenticationAdmin.md +25 -0
  89. package/docs/reference/functions/generateRestRoutesAuthenticationAudit.md +25 -0
  90. package/docs/reference/index.md +20 -0
  91. package/docs/reference/interfaces/IAuthHeaderProcessorConfig.md +4 -4
  92. package/docs/reference/interfaces/IAuthHeaderProcessorConstructorOptions.md +40 -4
  93. package/docs/reference/interfaces/IEntityStorageAuthenticationAdminServiceConfig.md +2 -2
  94. package/docs/reference/interfaces/IEntityStorageAuthenticationAdminServiceConstructorOptions.md +18 -4
  95. package/docs/reference/interfaces/IEntityStorageAuthenticationAuditServiceConfig.md +11 -0
  96. package/docs/reference/interfaces/IEntityStorageAuthenticationAuditServiceConstructorOptions.md +25 -0
  97. package/docs/reference/interfaces/IEntityStorageAuthenticationRateServiceConfig.md +17 -0
  98. package/docs/reference/interfaces/IEntityStorageAuthenticationRateServiceConstructorOptions.md +39 -0
  99. package/docs/reference/interfaces/IEntityStorageAuthenticationServiceConfig.md +61 -5
  100. package/docs/reference/interfaces/IEntityStorageAuthenticationServiceConstructorOptions.md +46 -10
  101. package/docs/reference/variables/tagsAuthenticationAdmin.md +5 -0
  102. package/docs/reference/variables/tagsAuthenticationAudit.md +5 -0
  103. package/locales/en.json +17 -3
  104. package/package.json +8 -7
@@ -1 +1 @@
1
- {"version":3,"file":"tokenHelper.js","sourceRoot":"","sources":["../../../src/utils/tokenHelper.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,OAAO,EAAwB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EACN,YAAY,EACZ,WAAW,EAIX,GAAG,EACH,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,OAAO,WAAW;IACvB;;OAEG;IACI,MAAM,CAAU,UAAU,iBAAiC;IAElE;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,CAAC,WAAW,CAC9B,cAA+B,EAC/B,cAAsB,EACtB,YAAoB,EACpB,oBAAwC,EACxC,UAAkB;QAKlB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,UAAU,GAAG,EAAE,CAAC;QAEnC,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,gBAAgB,CACrC,EAAE,GAAG,EAAE,OAAO,EAAE,EAChB;YACC,GAAG,EAAE,YAAY;YACjB,GAAG,EAAE,oBAAoB;YACzB,GAAG,EAAE,UAAU,GAAG,UAAU;SAC5B,EACD,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CACzB,oBAAoB,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAChF,CAAC;QAEF,OAAO;YACN,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,IAAI;SACxC,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACI,MAAM,CAAC,KAAK,CAAC,MAAM,CACzB,cAA+B,EAC/B,cAAsB,EACtB,KAAyB;QAKzB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE,CAC7D,oBAAoB,CAAC,WAAW,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC,CACnE,CAAC;QAEF,wFAAwF;QACxF,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;QAC9E,CAAC;aAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,4BAA4B,CAAC,CAAC;QACnF,CAAC;aAAM,IACN,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;YAC/B,OAAO,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAClD,CAAC;YACF,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAChE,CAAC;QAED,OAAO;YACN,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;SACxB,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,uBAAuB,CACpC,OAAsB,EACtB,UAAmB;QAOnB,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,OAAO,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEpD,MAAM,WAAW,GAAG,YAAY,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;YACjC,OAAO;gBACN,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,eAAe;aACzB,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YACrE,MAAM,OAAO,GAAG,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;YAC/E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC9B,IAAI,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC5B,MAAM,iBAAiB,GAAG,MAAM;yBAC9B,KAAK,CAAC,GAAG,CAAC;yBACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;yBAClB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC;oBACtC,IAAI,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC,EAAE,CAAC;wBACvC,OAAO;4BACN,KAAK,EAAE,iBAAiB,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;4BAC5D,QAAQ,EAAE,QAAQ;yBAClB,CAAC;oBACH,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { Is, UnauthorizedError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type IVaultConnector, VaultConnectorHelper } from \"@twin.org/vault-models\";\nimport {\n\tHeaderHelper,\n\tHeaderTypes,\n\ttype IHttpHeaders,\n\ttype IJwtHeader,\n\ttype IJwtPayload,\n\tJwt\n} from \"@twin.org/web\";\n\n/**\n * Helper class for token operations.\n */\nexport class TokenHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TokenHelper>();\n\n\t/**\n\t * Create a new token.\n\t * @param vaultConnector The vault connector.\n\t * @param signingKeyName The signing key name.\n\t * @param userIdentity The subject for the token.\n\t * @param organizationIdentity The organization for the token.\n\t * @param ttlMinutes The time to live for the token in minutes.\n\t * @returns The new token and its expiry date.\n\t */\n\tpublic static async createToken(\n\t\tvaultConnector: IVaultConnector,\n\t\tsigningKeyName: string,\n\t\tuserIdentity: string,\n\t\torganizationIdentity: string | undefined,\n\t\tttlMinutes: number\n\t): Promise<{\n\t\ttoken: string;\n\t\texpiry: number;\n\t}> {\n\t\tconst nowSeconds = Math.trunc(Date.now() / 1000);\n\t\tconst ttlSeconds = ttlMinutes * 60;\n\n\t\tconst jwt = await Jwt.encodeWithSigner(\n\t\t\t{ alg: \"EdDSA\" },\n\t\t\t{\n\t\t\t\tsub: userIdentity,\n\t\t\t\torg: organizationIdentity,\n\t\t\t\texp: nowSeconds + ttlSeconds\n\t\t\t},\n\t\t\tasync (header, payload) =>\n\t\t\t\tVaultConnectorHelper.jwtSigner(vaultConnector, signingKeyName, header, payload)\n\t\t);\n\n\t\treturn {\n\t\t\ttoken: jwt,\n\t\t\texpiry: (nowSeconds + ttlSeconds) * 1000\n\t\t};\n\t}\n\n\t/**\n\t * Verify the token.\n\t * @param vaultConnector The vault connector.\n\t * @param signingKeyName The signing key name.\n\t * @param token The token to verify.\n\t * @returns The verified details.\n\t * @throws UnauthorizedError if the token is missing, invalid or expired.\n\t */\n\tpublic static async verify(\n\t\tvaultConnector: IVaultConnector,\n\t\tsigningKeyName: string,\n\t\ttoken: string | undefined\n\t): Promise<{\n\t\theader: IJwtHeader;\n\t\tpayload: IJwtPayload;\n\t}> {\n\t\tif (!Is.stringValue(token)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"missing\");\n\t\t}\n\n\t\tconst decoded = await Jwt.verifyWithVerifier(token, async t =>\n\t\t\tVaultConnectorHelper.jwtVerifier(vaultConnector, signingKeyName, t)\n\t\t);\n\n\t\t// If some of the header/payload data is not properly populated then it is unauthorized.\n\t\tif (!Is.stringValue(decoded.payload.sub)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"payloadMissingSubject\");\n\t\t} else if (!Is.stringValue(decoded.payload.org)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"payloadMissingOrganization\");\n\t\t} else if (\n\t\t\t!Is.empty(decoded.payload?.exp) &&\n\t\t\tdecoded.payload.exp < Math.trunc(Date.now() / 1000)\n\t\t) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"expired\");\n\t\t}\n\n\t\treturn {\n\t\t\theader: decoded.header,\n\t\t\tpayload: decoded.payload\n\t\t};\n\t}\n\n\t/**\n\t * Extract the auth token from the headers, either from the authorization header or the cookie header.\n\t * @param headers The headers to extract the token from.\n\t * @param cookieName The name of the cookie to extract the token from.\n\t * @returns The token if found.\n\t */\n\tpublic static extractTokenFromHeaders(\n\t\theaders?: IHttpHeaders,\n\t\tcookieName?: string\n\t):\n\t\t| {\n\t\t\t\ttoken: string;\n\t\t\t\tlocation: \"authorization\" | \"cookie\";\n\t\t }\n\t\t| undefined {\n\t\tconst authHeader = headers?.[HeaderTypes.Authorization];\n\t\tconst cookiesHeader = headers?.[HeaderTypes.Cookie];\n\n\t\tconst bearerToken = HeaderHelper.extractBearer(authHeader);\n\t\tif (Is.stringValue(bearerToken)) {\n\t\t\treturn {\n\t\t\t\ttoken: bearerToken,\n\t\t\t\tlocation: \"authorization\"\n\t\t\t};\n\t\t} else if (Is.notEmpty(cookiesHeader) && Is.stringValue(cookieName)) {\n\t\t\tconst cookies = Is.arrayValue(cookiesHeader) ? cookiesHeader : [cookiesHeader];\n\t\t\tfor (const cookie of cookies) {\n\t\t\t\tif (Is.stringValue(cookie)) {\n\t\t\t\t\tconst accessTokenCookie = cookie\n\t\t\t\t\t\t.split(\";\")\n\t\t\t\t\t\t.map(c => c.trim())\n\t\t\t\t\t\t.find(c => c.startsWith(cookieName));\n\t\t\t\t\tif (Is.stringValue(accessTokenCookie)) {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttoken: accessTokenCookie.slice(cookieName.length + 1).trim(),\n\t\t\t\t\t\t\tlocation: \"cookie\"\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"tokenHelper.js","sourceRoot":"","sources":["../../../src/utils/tokenHelper.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAAwB,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AACpF,OAAO,EACN,YAAY,EACZ,YAAY,EACZ,WAAW,EAIX,GAAG,EACH,MAAM,eAAe,CAAC;AAEvB;;GAEG;AACH,MAAM,OAAO,WAAW;IACvB;;OAEG;IACI,MAAM,CAAU,UAAU,iBAAiC;IAElE;;;;;;;;;;;;OAYG;IACI,MAAM,CAAC,KAAK,CAAC,WAAW,CAC9B,cAA+B,EAC/B,uBAAiD,EACjD,cAAsB,EACtB,YAAoB,EACpB,oBAAwC,EACxC,QAA4B,EAC5B,UAAkB,EAClB,KAAc,EACd,eAAwB;QAKxB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QACjD,MAAM,UAAU,GAAG,UAAU,GAAG,EAAE,CAAC;QAEnC,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,gBAAgB,CACrC,EAAE,GAAG,EAAE,OAAO,EAAE,EAChB;YACC,GAAG,EAAE,YAAY;YACjB,GAAG,EAAE,oBAAoB;YACzB,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC;gBAC5B,CAAC,CAAC,MAAM,uBAAuB,CAAC,YAAY,CAAC,QAAQ,CAAC;gBACtD,CAAC,CAAC,SAAS;YACZ,GAAG,EAAE,UAAU,GAAG,UAAU;YAC5B,KAAK;YACL,IAAI,EAAE,eAAe;SACrB,EACD,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,CACzB,oBAAoB,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,CAChF,CAAC;QAEF,OAAO;YACN,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,CAAC,UAAU,GAAG,UAAU,CAAC,GAAG,IAAI;SACxC,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACI,MAAM,CAAC,KAAK,CAAC,MAAM,CACzB,cAA+B,EAC/B,cAAsB,EACtB,KAAyB,EACzB,cAAyB,EACzB,UAKsB;QAKtB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAChE,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE,CAC7D,oBAAoB,CAAC,WAAW,CAAC,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC,CACnE,CAAC;QAEF,wFAAwF;QACxF,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,uBAAuB,CAAC,CAAC;QAC9E,CAAC;aAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,4BAA4B,CAAC,CAAC;QACnF,CAAC;aAAM,IACN,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;YAC/B,OAAO,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAClD,CAAC;YACF,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAChE,CAAC;QAED,IAAI,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7B,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,YAAY,GAAG,MAAM,UAAU,CACpC,OAAO,CAAC,OAAO,CAAC,GAAG,EACnB,OAAO,CAAC,OAAO,CAAC,GAAG,EACnB,iBAAiB,EACjB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CACpC,CAAC;YACF,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACpC,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC;YACxE,CAAC;iBAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnD,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC;YAChF,CAAC;iBAAM,IAAI,EAAE,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAClF,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC;YAC1E,CAAC;QACF,CAAC;QAED,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACnC,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;gBACxD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC;gBAClC,CAAC,CAAC,EAAE,CAAC;YAEN,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;gBAC5C,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBAC1C,MAAM,IAAI,iBAAiB,CAAC,WAAW,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;gBAC3E,CAAC;YACF,CAAC;QACF,CAAC;QAED,OAAO;YACN,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,OAAO,EAAE,OAAO,CAAC,OAAO;SACxB,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,uBAAuB,CACpC,OAAsB,EACtB,UAAmB;QAOnB,MAAM,UAAU,GAAG,OAAO,EAAE,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,OAAO,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEpD,MAAM,WAAW,GAAG,YAAY,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC;YACjC,OAAO;gBACN,KAAK,EAAE,WAAW;gBAClB,QAAQ,EAAE,eAAe;aACzB,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YACrE,MAAM,KAAK,GAAG,YAAY,CAAC,oBAAoB,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;YAC3E,IAAI,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO;oBACN,KAAK,EAAE,KAAK;oBACZ,QAAQ,EAAE,QAAQ;iBAClB,CAAC;YACH,CAAC;QACF,CAAC;IACF,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IUrlTransformerComponent } from \"@twin.org/api-models\";\nimport { Coerce, Is, UnauthorizedError } from \"@twin.org/core\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { type IVaultConnector, VaultConnectorHelper } from \"@twin.org/vault-models\";\nimport {\n\tCookieHelper,\n\tHeaderHelper,\n\tHeaderTypes,\n\ttype IHttpHeaders,\n\ttype IJwtHeader,\n\ttype IJwtPayload,\n\tJwt\n} from \"@twin.org/web\";\n\n/**\n * Helper class for token operations.\n */\nexport class TokenHelper {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<TokenHelper>();\n\n\t/**\n\t * Create a new token.\n\t * @param vaultConnector The vault connector.\n\t * @param urlTransformerComponent The URL transformer component, used to encrypt the tenant ID for inclusion in the token.\n\t * @param signingKeyName The signing key name.\n\t * @param userIdentity The subject for the token.\n\t * @param organizationIdentity The organization for the token.\n\t * @param tenantId The tenant id for the token.\n\t * @param ttlMinutes The time to live for the token in minutes.\n\t * @param scope The scopes for the token.\n\t * @param passwordVersion The user's current password version counter, embedded in the token so that a password change invalidates existing tokens.\n\t * @returns The new token and its expiry date.\n\t */\n\tpublic static async createToken(\n\t\tvaultConnector: IVaultConnector,\n\t\turlTransformerComponent: IUrlTransformerComponent,\n\t\tsigningKeyName: string,\n\t\tuserIdentity: string,\n\t\torganizationIdentity: string | undefined,\n\t\ttenantId: string | undefined,\n\t\tttlMinutes: number,\n\t\tscope?: string,\n\t\tpasswordVersion?: number\n\t): Promise<{\n\t\ttoken: string;\n\t\texpiry: number;\n\t}> {\n\t\tconst nowSeconds = Math.trunc(Date.now() / 1000);\n\t\tconst ttlSeconds = ttlMinutes * 60;\n\n\t\tconst jwt = await Jwt.encodeWithSigner(\n\t\t\t{ alg: \"EdDSA\" },\n\t\t\t{\n\t\t\t\tsub: userIdentity,\n\t\t\t\torg: organizationIdentity,\n\t\t\t\ttid: Is.stringValue(tenantId)\n\t\t\t\t\t? await urlTransformerComponent.encryptParam(tenantId)\n\t\t\t\t\t: undefined,\n\t\t\t\texp: nowSeconds + ttlSeconds,\n\t\t\t\tscope,\n\t\t\t\tpver: passwordVersion\n\t\t\t},\n\t\t\tasync (header, payload) =>\n\t\t\t\tVaultConnectorHelper.jwtSigner(vaultConnector, signingKeyName, header, payload)\n\t\t);\n\n\t\treturn {\n\t\t\ttoken: jwt,\n\t\t\texpiry: (nowSeconds + ttlSeconds) * 1000\n\t\t};\n\t}\n\n\t/**\n\t * Verify the token.\n\t * @param vaultConnector The vault connector.\n\t * @param signingKeyName The signing key name.\n\t * @param token The token to verify.\n\t * @param requiredScopes The required scopes.\n\t * @param verifyUser A function to verify the user identity and organization. The password version counter embedded in the token (pver claim) is passed so callers can detect if the password has changed since the token was issued.\n\t * @returns The verified details.\n\t * @throws UnauthorizedError if the token is missing, invalid or expired.\n\t */\n\tpublic static async verify(\n\t\tvaultConnector: IVaultConnector,\n\t\tsigningKeyName: string,\n\t\ttoken: string | undefined,\n\t\trequiredScopes?: string[],\n\t\tverifyUser?: (\n\t\t\tuserIdentity: string,\n\t\t\torganizationIdentity: string,\n\t\t\tencryptedTenantId: string | undefined,\n\t\t\tpasswordVersion: number | undefined\n\t\t) => Promise<string[]>\n\t): Promise<{\n\t\theader: IJwtHeader;\n\t\tpayload: IJwtPayload;\n\t}> {\n\t\tif (!Is.stringValue(token)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"missing\");\n\t\t}\n\n\t\tconst decoded = await Jwt.verifyWithVerifier(token, async t =>\n\t\t\tVaultConnectorHelper.jwtVerifier(vaultConnector, signingKeyName, t)\n\t\t);\n\n\t\t// If some of the header/payload data is not properly populated then it is unauthorized.\n\t\tif (!Is.stringValue(decoded.payload.sub)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"payloadMissingSubject\");\n\t\t} else if (!Is.stringValue(decoded.payload.org)) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"payloadMissingOrganization\");\n\t\t} else if (\n\t\t\t!Is.empty(decoded.payload?.exp) &&\n\t\t\tdecoded.payload.exp < Math.trunc(Date.now() / 1000)\n\t\t) {\n\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"expired\");\n\t\t}\n\n\t\tif (Is.function(verifyUser)) {\n\t\t\tconst encryptedTenantId = Coerce.string(decoded.payload.tid);\n\t\t\tconst userVerified = await verifyUser(\n\t\t\t\tdecoded.payload.sub,\n\t\t\t\tdecoded.payload.org,\n\t\t\t\tencryptedTenantId,\n\t\t\t\tCoerce.integer(decoded.payload.pver)\n\t\t\t);\n\t\t\tif (!userVerified.includes(\"user\")) {\n\t\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"userNotVerified\");\n\t\t\t} else if (!userVerified.includes(\"organization\")) {\n\t\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"organizationNotVerified\");\n\t\t\t} else if (Is.stringValue(encryptedTenantId) && !userVerified.includes(\"tenant\")) {\n\t\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"tenantNotVerified\");\n\t\t\t}\n\t\t}\n\n\t\tif (Is.arrayValue(requiredScopes)) {\n\t\t\tconst tokenScopes = Is.stringValue(decoded.payload.scope)\n\t\t\t\t? decoded.payload.scope.split(\",\")\n\t\t\t\t: [];\n\n\t\t\tfor (const requiredScope of requiredScopes) {\n\t\t\t\tif (!tokenScopes.includes(requiredScope)) {\n\t\t\t\t\tthrow new UnauthorizedError(TokenHelper.CLASS_NAME, \"insufficientScopes\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\theader: decoded.header,\n\t\t\tpayload: decoded.payload\n\t\t};\n\t}\n\n\t/**\n\t * Extract the auth token from the headers, either from the authorization header or the cookie header.\n\t * @param headers The headers to extract the token from.\n\t * @param cookieName The name of the cookie to extract the token from.\n\t * @returns The token if found.\n\t */\n\tpublic static extractTokenFromHeaders(\n\t\theaders?: IHttpHeaders,\n\t\tcookieName?: string\n\t):\n\t\t| {\n\t\t\t\ttoken: string;\n\t\t\t\tlocation: \"authorization\" | \"cookie\";\n\t\t }\n\t\t| undefined {\n\t\tconst authHeader = headers?.[HeaderTypes.Authorization];\n\t\tconst cookiesHeader = headers?.[HeaderTypes.Cookie];\n\n\t\tconst bearerToken = HeaderHelper.extractBearer(authHeader);\n\t\tif (Is.stringValue(bearerToken)) {\n\t\t\treturn {\n\t\t\t\ttoken: bearerToken,\n\t\t\t\tlocation: \"authorization\"\n\t\t\t};\n\t\t} else if (Is.notEmpty(cookiesHeader) && Is.stringValue(cookieName)) {\n\t\t\tconst value = CookieHelper.getCookieFromHeaders(cookiesHeader, cookieName);\n\t\t\tif (Is.stringValue(value)) {\n\t\t\t\treturn {\n\t\t\t\t\ttoken: value,\n\t\t\t\t\tlocation: \"cookie\"\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Class defining the storage for authentication audit entries.
3
+ */
4
+ export declare class AuthenticationAuditEntry {
5
+ /**
6
+ * The unique identifier for the audit entry.
7
+ */
8
+ id: string;
9
+ /**
10
+ * The timestamp of the audit entry in ISO 8601 format.
11
+ */
12
+ dateCreated: string;
13
+ /**
14
+ * The audit event that occurred.
15
+ */
16
+ event: string;
17
+ /**
18
+ * The actor identifier, could be e-mail, username, or other unique identifier.
19
+ */
20
+ actorId?: string;
21
+ /**
22
+ * The node identifier associated with the audit entry, if applicable.
23
+ */
24
+ nodeId?: string;
25
+ /**
26
+ * The organization identifier associated with the audit entry, if applicable.
27
+ */
28
+ organizationId?: string;
29
+ /**
30
+ * The tenant identifier associated with the audit entry, if applicable.
31
+ */
32
+ tenantId?: string;
33
+ /**
34
+ * The hashed IP addresses of the client.
35
+ */
36
+ ipAddressHashes?: string[];
37
+ /**
38
+ * The user agent string of the client.
39
+ */
40
+ userAgent?: string;
41
+ /**
42
+ * The correlation ID for request tracing.
43
+ */
44
+ correlationId?: string;
45
+ /**
46
+ * Additional data related to the audit entry, such as IP address, user agent, etc.
47
+ */
48
+ data?: unknown;
49
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Class defining the storage for authentication rate entries.
3
+ */
4
+ export declare class AuthenticationRateEntry {
5
+ /**
6
+ * The id for the rate entry.
7
+ */
8
+ id: string;
9
+ /**
10
+ * Array of ISO date strings representing timestamps of failed attempts.
11
+ */
12
+ timestamps: string[];
13
+ /**
14
+ * Last modification time in ISO date format.
15
+ */
16
+ dateModified: string;
17
+ }
@@ -22,4 +22,12 @@ export declare class AuthenticationUser {
22
22
  * The users organization.
23
23
  */
24
24
  organization: string;
25
+ /**
26
+ * The scope assigned to the user, comma separated.
27
+ */
28
+ scope: string;
29
+ /**
30
+ * The password version counter, incremented on every password change to invalidate existing tokens.
31
+ */
32
+ passwordVersion?: number;
25
33
  }
@@ -1,15 +1,25 @@
1
+ export * from "./entities/authenticationAuditEntry.js";
2
+ export * from "./entities/authenticationRateEntry.js";
1
3
  export * from "./entities/authenticationUser.js";
2
4
  export * from "./models/IAuthHeaderProcessorConfig.js";
3
5
  export * from "./models/IAuthHeaderProcessorConstructorOptions.js";
4
6
  export * from "./models/IEntityStorageAuthenticationAdminServiceConfig.js";
5
7
  export * from "./models/IEntityStorageAuthenticationAdminServiceConstructorOptions.js";
8
+ export * from "./models/IEntityStorageAuthenticationAuditServiceConfig.js";
9
+ export * from "./models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js";
10
+ export * from "./models/IEntityStorageAuthenticationRateServiceConfig.js";
11
+ export * from "./models/IEntityStorageAuthenticationRateServiceConstructorOptions.js";
6
12
  export * from "./models/IEntityStorageAuthenticationServiceConfig.js";
7
13
  export * from "./models/IEntityStorageAuthenticationServiceConstructorOptions.js";
8
14
  export * from "./processors/authHeaderProcessor.js";
9
15
  export * from "./restEntryPoints.js";
16
+ export * from "./routes/entityStorageAuthenticationAdminRoutes.js";
17
+ export * from "./routes/entityStorageAuthenticationAuditRoutes.js";
10
18
  export * from "./routes/entityStorageAuthenticationRoutes.js";
11
19
  export * from "./schema.js";
12
20
  export * from "./services/entityStorageAuthenticationAdminService.js";
21
+ export * from "./services/entityStorageAuthenticationAuditService.js";
22
+ export * from "./services/entityStorageAuthenticationRateService.js";
13
23
  export * from "./services/entityStorageAuthenticationService.js";
14
- export * from "./utils/passwordHelper.js";
15
24
  export * from "./utils/tokenHelper.js";
25
+ export * from "./utils/passwordHelper.js";
@@ -3,11 +3,25 @@ import type { IAuthHeaderProcessorConfig } from "./IAuthHeaderProcessorConfig.js
3
3
  * Options for the AuthHeaderProcessor constructor.
4
4
  */
5
5
  export interface IAuthHeaderProcessorConstructorOptions {
6
+ /**
7
+ * The entity storage for users.
8
+ * @default authentication-user
9
+ */
10
+ userEntityStorageType?: string;
6
11
  /**
7
12
  * The vault for the private keys.
8
13
  * @default vault
9
14
  */
10
15
  vaultConnectorType?: string;
16
+ /**
17
+ * The URL transformer component for the tenants.
18
+ */
19
+ urlTransformerComponentType?: string;
20
+ /**
21
+ * The component to retrieve tenant information.
22
+ * @default tenant-admin
23
+ */
24
+ tenantAdminComponentType?: string;
11
25
  /**
12
26
  * The configuration for the processor.
13
27
  */
@@ -8,6 +8,11 @@ export interface IEntityStorageAuthenticationAdminServiceConstructorOptions {
8
8
  * @default authentication-user
9
9
  */
10
10
  userEntityStorageType?: string;
11
+ /**
12
+ * The audit service.
13
+ * @default authentication-audit
14
+ */
15
+ authenticationAuditServiceType?: string;
11
16
  /**
12
17
  * The configuration for the authentication.
13
18
  */
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Config for the EntityStorageAuthenticationAuditService constructor.
3
+ */
4
+ export interface IEntityStorageAuthenticationAuditServiceConfig {
5
+ /**
6
+ * The server-side salt for hashing IP addresses in audit logs, if configured.
7
+ */
8
+ ipHashSalt?: string;
9
+ }
@@ -0,0 +1,15 @@
1
+ import type { IEntityStorageAuthenticationAuditServiceConfig } from "./IEntityStorageAuthenticationAuditServiceConfig.js";
2
+ /**
3
+ * Options for the EntityStorageAuthenticationAuditService constructor.
4
+ */
5
+ export interface IEntityStorageAuthenticationAuditServiceConstructorOptions {
6
+ /**
7
+ * The entity storage for the audit entries.
8
+ * @default authentication-audit-entry
9
+ */
10
+ authenticationAuditEntryStorageType?: string;
11
+ /**
12
+ * The configuration for the authentication audit service.
13
+ */
14
+ config?: IEntityStorageAuthenticationAuditServiceConfig;
15
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Configuration for the entity storage authentication rate service.
3
+ */
4
+ export interface IEntityStorageAuthenticationRateServiceConfig {
5
+ /**
6
+ * Interval between cleanup runs in minutes.
7
+ * @default 5
8
+ */
9
+ cleanupIntervalMinutes?: number;
10
+ }
@@ -0,0 +1,20 @@
1
+ import type { IEntityStorageAuthenticationRateServiceConfig } from "./IEntityStorageAuthenticationRateServiceConfig.js";
2
+ /**
3
+ * Options for the EntityStorageAuthenticationRateService constructor.
4
+ */
5
+ export interface IEntityStorageAuthenticationRateServiceConstructorOptions {
6
+ /**
7
+ * The entity storage for authentication rate entries.
8
+ * @default authentication-rate-entry
9
+ */
10
+ authenticationRateEntryStorageType?: string;
11
+ /**
12
+ * The task scheduler component type.
13
+ * @default task-scheduler
14
+ */
15
+ taskSchedulerComponentType?: string;
16
+ /**
17
+ * The configuration for the authentication rate service.
18
+ */
19
+ config?: IEntityStorageAuthenticationRateServiceConfig;
20
+ }
@@ -1,3 +1,4 @@
1
+ import type { IAuthenticationRateActionConfig } from "@twin.org/api-auth-entity-storage-models";
1
2
  /**
2
3
  * Configuration for the entity storage authentication service.
3
4
  */
@@ -9,7 +10,27 @@ export interface IEntityStorageAuthenticationServiceConfig {
9
10
  signingKeyName?: string;
10
11
  /**
11
12
  * The default time to live for the JWT.
12
- * @default 1440
13
+ * @default 60
13
14
  */
14
15
  defaultTtlMinutes?: number;
16
+ /**
17
+ * The minimum password length for new password validation.
18
+ * @default 8
19
+ */
20
+ minPasswordLength?: number;
21
+ /**
22
+ * Optional override for login failure rate limit.
23
+ * @default { maxAttempts: 5, windowMinutes: 15 }
24
+ */
25
+ loginRateLimit?: IAuthenticationRateActionConfig;
26
+ /**
27
+ * Optional override for password change rate limit.
28
+ * @default { maxAttempts: 5, windowMinutes: 15 }
29
+ */
30
+ passwordChangeRateLimit?: IAuthenticationRateActionConfig;
31
+ /**
32
+ * Optional override for token refresh rate limit.
33
+ * @default { maxAttempts: 30, windowMinutes: 60 }
34
+ */
35
+ tokenRefreshRateLimit?: IAuthenticationRateActionConfig;
15
36
  }
@@ -14,10 +14,24 @@ export interface IEntityStorageAuthenticationServiceConstructorOptions {
14
14
  */
15
15
  vaultConnectorType?: string;
16
16
  /**
17
- * The admin service.
18
- * @default authentication-admin
17
+ * The URL transformer component for the tenants.
19
18
  */
20
- authenticationAdminServiceType?: string;
19
+ urlTransformerComponentType?: string;
20
+ /**
21
+ * The audit service.
22
+ * @default authentication-audit
23
+ */
24
+ authenticationAuditServiceType?: string;
25
+ /**
26
+ * The rate service.
27
+ * @default authentication-rate
28
+ */
29
+ authenticationRateServiceType?: string;
30
+ /**
31
+ * The component to retrieve tenant information.
32
+ * @default tenant-admin
33
+ */
34
+ tenantAdminComponentType?: string;
21
35
  /**
22
36
  * The configuration for the authentication.
23
37
  */
@@ -10,7 +10,7 @@ export declare class AuthHeaderProcessor implements IBaseRouteProcessor {
10
10
  */
11
11
  static readonly CLASS_NAME: string;
12
12
  /**
13
- * Create a new instance of AuthCookiePreProcessor.
13
+ * Create a new instance of AuthHeaderProcessor.
14
14
  * @param options Options for the processor.
15
15
  */
16
16
  constructor(options?: IAuthHeaderProcessorConstructorOptions);
@@ -0,0 +1,61 @@
1
+ import type { IAdminUserCreateRequest, IAdminUserGetByIdentityRequest, IAdminUserGetRequest, IAdminUserGetResponse, IAdminUserRemoveRequest, IAdminUserUpdatePasswordRequest, IAdminUserUpdateRequest } from "@twin.org/api-auth-entity-storage-models";
2
+ import type { ICreatedResponse, IHttpRequestContext, INoContentResponse, IRestRoute, ITag } from "@twin.org/api-models";
3
+ /**
4
+ * The tag to associate with the routes.
5
+ */
6
+ export declare const tagsAuthenticationAdmin: ITag[];
7
+ /**
8
+ * The REST routes for authentication admin.
9
+ * @param baseRouteName Prefix to prepend to the paths.
10
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
11
+ * @returns The generated routes.
12
+ */
13
+ export declare function generateRestRoutesAuthenticationAdmin(baseRouteName: string, componentName: string): IRestRoute[];
14
+ /**
15
+ * Create a new user.
16
+ * @param httpRequestContext The request context for the API.
17
+ * @param componentName The name of the component to use in the routes.
18
+ * @param request The request.
19
+ * @returns The response object with additional http response properties.
20
+ */
21
+ export declare function authenticationAdminCreateUser(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserCreateRequest): Promise<ICreatedResponse>;
22
+ /**
23
+ * Update an existing user.
24
+ * @param httpRequestContext The request context for the API.
25
+ * @param componentName The name of the component to use in the routes.
26
+ * @param request The request.
27
+ * @returns The response object with additional http response properties.
28
+ */
29
+ export declare function authenticationAdminUpdateUser(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserUpdateRequest): Promise<INoContentResponse>;
30
+ /**
31
+ * Update an existing user password.
32
+ * @param httpRequestContext The request context for the API.
33
+ * @param componentName The name of the component to use in the routes.
34
+ * @param request The request.
35
+ * @returns The response object with additional http response properties.
36
+ */
37
+ export declare function authenticationAdminUpdateUserPassword(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserUpdatePasswordRequest): Promise<INoContentResponse>;
38
+ /**
39
+ * Get an existing user.
40
+ * @param httpRequestContext The request context for the API.
41
+ * @param componentName The name of the component to use in the routes.
42
+ * @param request The request.
43
+ * @returns The response object with additional http response properties.
44
+ */
45
+ export declare function authenticationAdminGetUser(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserGetRequest): Promise<IAdminUserGetResponse>;
46
+ /**
47
+ * Get an existing user by identity.
48
+ * @param httpRequestContext The request context for the API.
49
+ * @param componentName The name of the component to use in the routes.
50
+ * @param request The request.
51
+ * @returns The response object with additional http response properties.
52
+ */
53
+ export declare function authenticationAdminGetUserByIdentity(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserGetByIdentityRequest): Promise<IAdminUserGetResponse>;
54
+ /**
55
+ * Remove an existing user.
56
+ * @param httpRequestContext The request context for the API.
57
+ * @param componentName The name of the component to use in the routes.
58
+ * @param request The request.
59
+ * @returns The response object with additional http response properties.
60
+ */
61
+ export declare function authenticationAdminRemoveUser(httpRequestContext: IHttpRequestContext, componentName: string, request: IAdminUserRemoveRequest): Promise<INoContentResponse>;
@@ -0,0 +1,29 @@
1
+ import type { IAuditCreateRequest, IAuditQueryRequest, IAuditQueryResponse } from "@twin.org/api-auth-entity-storage-models";
2
+ import type { ICreatedResponse, IHttpRequestContext, IRestRoute, ITag } from "@twin.org/api-models";
3
+ /**
4
+ * The tag to associate with the routes.
5
+ */
6
+ export declare const tagsAuthenticationAudit: ITag[];
7
+ /**
8
+ * The REST routes for authentication audit.
9
+ * @param baseRouteName Prefix to prepend to the paths.
10
+ * @param componentName The name of the component to use in the routes stored in the ComponentFactory.
11
+ * @returns The generated routes.
12
+ */
13
+ export declare function generateRestRoutesAuthenticationAudit(baseRouteName: string, componentName: string): IRestRoute[];
14
+ /**
15
+ * Create an authentication audit entry.
16
+ * @param httpRequestContext The request context for the API.
17
+ * @param componentName The name of the component to use in the routes.
18
+ * @param request The request.
19
+ * @returns The response object with additional http response properties.
20
+ */
21
+ export declare function authenticationAuditCreate(httpRequestContext: IHttpRequestContext, componentName: string, request: IAuditCreateRequest): Promise<ICreatedResponse>;
22
+ /**
23
+ * Query authentication audit entries.
24
+ * @param httpRequestContext The request context for the API.
25
+ * @param componentName The name of the component to use in the routes.
26
+ * @param request The request.
27
+ * @returns The response object with additional http response properties.
28
+ */
29
+ export declare function authenticationAuditQuery(httpRequestContext: IHttpRequestContext, componentName: string, request: IAuditQueryRequest): Promise<IAuditQueryResponse>;
@@ -1,4 +1,4 @@
1
- import type { IAuthenticationAdminComponent } from "@twin.org/api-auth-entity-storage-models";
1
+ import type { IAuthenticationAdminComponent, IAuthenticationUser } from "@twin.org/api-auth-entity-storage-models";
2
2
  import type { IEntityStorageAuthenticationAdminServiceConstructorOptions } from "../models/IEntityStorageAuthenticationAdminServiceConstructorOptions.js";
3
3
  /**
4
4
  * Implementation of the authentication component using entity storage.
@@ -20,13 +20,30 @@ export declare class EntityStorageAuthenticationAdminService implements IAuthent
20
20
  className(): string;
21
21
  /**
22
22
  * Create a login for the user.
23
- * @param email The email address for the user.
24
- * @param password The password for the user.
25
- * @param userIdentity The DID to associate with the account.
26
- * @param organizationIdentity The organization of the user.
23
+ * @param user The user to create.
27
24
  * @returns Nothing.
28
25
  */
29
- create(email: string, password: string, userIdentity: string, organizationIdentity: string): Promise<void>;
26
+ create(user: IAuthenticationUser & {
27
+ password: string;
28
+ }): Promise<void>;
29
+ /**
30
+ * Update a login for the user.
31
+ * @param user The user to update.
32
+ * @returns Nothing.
33
+ */
34
+ update(user: Partial<IAuthenticationUser>): Promise<void>;
35
+ /**
36
+ * Get a user by email.
37
+ * @param email The email address of the user to get.
38
+ * @returns The user details.
39
+ */
40
+ get(email: string): Promise<IAuthenticationUser>;
41
+ /**
42
+ * Get a user by identity.
43
+ * @param identity The identity of the user to get.
44
+ * @returns The user details.
45
+ */
46
+ getByIdentity(identity: string): Promise<IAuthenticationUser>;
30
47
  /**
31
48
  * Remove the current user.
32
49
  * @param email The email address of the user to remove.
@@ -0,0 +1,59 @@
1
+ import type { AuthAuditEvent, IAuthenticationAuditComponent, IAuthenticationAuditEntry } from "@twin.org/api-auth-entity-storage-models";
2
+ import type { IEntityStorageAuthenticationAuditServiceConstructorOptions } from "../models/IEntityStorageAuthenticationAuditServiceConstructorOptions.js";
3
+ /**
4
+ * Implementation of the authentication audit component using entity storage.
5
+ */
6
+ export declare class EntityStorageAuthenticationAuditService implements IAuthenticationAuditComponent {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static readonly CLASS_NAME: string;
11
+ /**
12
+ * Create a new instance of EntityStorageAuthenticationAuditService.
13
+ * @param options The dependencies for the identity connector.
14
+ */
15
+ constructor(options?: IEntityStorageAuthenticationAuditServiceConstructorOptions);
16
+ /**
17
+ * Returns the class name of the component.
18
+ * @returns The class name of the component.
19
+ */
20
+ className(): string;
21
+ /**
22
+ * Create a new audit entry.
23
+ * @param entry The audit entry to be logged.
24
+ * @returns The unique identifier of the created audit entry.
25
+ */
26
+ create(entry: Omit<IAuthenticationAuditEntry, "id" | "dateCreated">): Promise<string>;
27
+ /**
28
+ * Query the audit entries.
29
+ * @param options The query options.
30
+ * @param options.actorId The actor identifier to filter the audit entries, optional.
31
+ * @param options.organizationId The organization identifier to filter the audit entries, optional.
32
+ * @param options.tenantId The tenant identifier to filter the audit entries, optional.
33
+ * @param options.nodeId The node identifier to filter the audit entries, optional.
34
+ * @param options.event The audit event to filter the audit entries, optional.
35
+ * @param options.startDate The start date to filter the audit entries, optional.
36
+ * @param options.endDate The end date to filter the audit entries, optional.
37
+ * @param cursor The cursor for pagination.
38
+ * @param limit The maximum number of entries to return.
39
+ * @returns The audit entries.
40
+ */
41
+ query(options?: {
42
+ actorId?: string;
43
+ organizationId?: string;
44
+ tenantId?: string;
45
+ nodeId?: string;
46
+ event?: AuthAuditEvent | string;
47
+ startDate?: string;
48
+ endDate?: string;
49
+ }, cursor?: string, limit?: number): Promise<{
50
+ entries: IAuthenticationAuditEntry[];
51
+ cursor?: string;
52
+ }>;
53
+ /**
54
+ * Hash a list of IP addresses using SHA-256.
55
+ * @param ipAddresses The IP addresses to hash.
56
+ * @returns The hexadecimal hashes of the salted IPs.
57
+ */
58
+ private hashIpAddresses;
59
+ }
@@ -0,0 +1,60 @@
1
+ import type { IAuthenticationRateActionConfig, IAuthenticationRateComponent } from "@twin.org/api-auth-entity-storage-models";
2
+ import type { IEntityStorageAuthenticationRateServiceConstructorOptions } from "../models/IEntityStorageAuthenticationRateServiceConstructorOptions.js";
3
+ /**
4
+ * Implementation of the authentication rate component using entity storage.
5
+ */
6
+ export declare class EntityStorageAuthenticationRateService implements IAuthenticationRateComponent {
7
+ /**
8
+ * Runtime name for the class.
9
+ */
10
+ static readonly CLASS_NAME: string;
11
+ /**
12
+ * Create a new instance of EntityStorageAuthenticationRateService.
13
+ * @param options The constructor options.
14
+ */
15
+ constructor(options?: IEntityStorageAuthenticationRateServiceConstructorOptions);
16
+ /**
17
+ * Register or update rate-limit configuration for an action.
18
+ * @param action The action name.
19
+ * @param config The action configuration.
20
+ * @returns Nothing.
21
+ */
22
+ registerAction(action: string, config: IAuthenticationRateActionConfig): Promise<void>;
23
+ /**
24
+ * Unregister rate-limit configuration for an action.
25
+ * @param action The action name.
26
+ * @returns Nothing.
27
+ */
28
+ unregisterAction(action: string): Promise<void>;
29
+ /**
30
+ * Returns the class name of the component.
31
+ * @returns The class name of the component.
32
+ */
33
+ className(): string;
34
+ /**
35
+ * The service needs to be started when the application is initialized.
36
+ * @param nodeLoggingComponentType The node logging component type.
37
+ * @returns Nothing.
38
+ */
39
+ start(nodeLoggingComponentType?: string): Promise<void>;
40
+ /**
41
+ * The component needs to be stopped when the node is closed.
42
+ * @param nodeLoggingComponentType The node logging component type.
43
+ * @returns Nothing.
44
+ */
45
+ stop(nodeLoggingComponentType?: string): Promise<void>;
46
+ /**
47
+ * Check the authentication rate for a given action and identifier.
48
+ * @param action The action to be checked.
49
+ * @param identifier The identifier to be checked.
50
+ * @returns The rate entry id.
51
+ */
52
+ check(action: string, identifier: string): Promise<string>;
53
+ /**
54
+ * Clear the authentication rate entry for the given action and identifier.
55
+ * @param action The action to clear.
56
+ * @param identifier The identifier to clear.
57
+ * @returns Nothing.
58
+ */
59
+ clear(action: string, identifier: string): Promise<void>;
60
+ }
@@ -24,6 +24,12 @@ export declare class EntityStorageAuthenticationService implements IAuthenticati
24
24
  * @returns Nothing.
25
25
  */
26
26
  start(nodeLoggingComponentType?: string): Promise<void>;
27
+ /**
28
+ * The component needs to be stopped when the node is closed.
29
+ * @param nodeLoggingComponentType The node logging component type.
30
+ * @returns Nothing.
31
+ */
32
+ stop(nodeLoggingComponentType?: string): Promise<void>;
27
33
  /**
28
34
  * Perform a login for the user.
29
35
  * @param email The email address for the user.
@@ -46,15 +52,14 @@ export declare class EntityStorageAuthenticationService implements IAuthenticati
46
52
  * @returns The refreshed token, if it uses a mechanism with public access.
47
53
  */
48
54
  refresh(token?: string): Promise<{
49
- token: string;
55
+ token?: string;
50
56
  expiry: number;
51
57
  }>;
52
58
  /**
53
59
  * Update the user's password.
54
- * @param email The email address of the user to update.
55
60
  * @param currentPassword The current password for the user.
56
61
  * @param newPassword The new password for the user.
57
62
  * @returns Nothing.
58
63
  */
59
- updatePassword(email: string, currentPassword: string, newPassword: string): Promise<void>;
64
+ updatePassword(currentPassword: string, newPassword: string): Promise<void>;
60
65
  }
@@ -1,3 +1,6 @@
1
+ import type { IAuthenticationAuditComponent } from "@twin.org/api-auth-entity-storage-models";
2
+ import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
3
+ import type { AuthenticationUser } from "../entities/authenticationUser.js";
1
4
  /**
2
5
  * Helper class for password operations.
3
6
  */
@@ -7,10 +10,15 @@ export declare class PasswordHelper {
7
10
  */
8
11
  static readonly CLASS_NAME: string;
9
12
  /**
10
- * Hash the password for the user.
11
- * @param passwordBytes The password bytes.
12
- * @param saltBytes The salt bytes.
13
- * @returns The hashed password.
13
+ * Update the password for a user.
14
+ * Validates password strength, verifies the current password if provided, then hashes and stores the new password and raises an audit event.
15
+ * @param userEntityStorage The entity storage for users.
16
+ * @param authenticationAuditService The optional audit service.
17
+ * @param user The user whose password is being updated.
18
+ * @param newPassword The new password to set.
19
+ * @param currentPassword The current password to verify against, if supplied.
20
+ * @param minPasswordLength Optional minimum password length for validation.
21
+ * @returns Nothing.
14
22
  */
15
- static hashPassword(passwordBytes: Uint8Array, saltBytes: Uint8Array): Promise<string>;
23
+ static updatePassword(userEntityStorage: IEntityStorageConnector<AuthenticationUser>, authenticationAuditService: IAuthenticationAuditComponent | undefined, user: AuthenticationUser, newPassword: string, currentPassword?: string, minPasswordLength?: number): Promise<void>;
16
24
  }