@authup/server-core 1.0.0-beta.61 → 1.0.0-beta.63

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 (216) hide show
  1. package/dist/adapters/database/domains/client-scope/entity.d.ts.map +1 -1
  2. package/dist/adapters/database/domains/client-scope/entity.mjs +16 -8
  3. package/dist/adapters/database/domains/client-scope/entity.mjs.map +1 -1
  4. package/dist/adapters/database/domains/identity-provider-account/entity.d.ts.map +1 -1
  5. package/dist/adapters/database/domains/identity-provider-account/entity.mjs +1 -1
  6. package/dist/adapters/database/domains/identity-provider-account/entity.mjs.map +1 -1
  7. package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts +8 -1
  8. package/dist/adapters/database/domains/identity-provider-attribute/subscriber.d.ts.map +1 -1
  9. package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs +14 -0
  10. package/dist/adapters/database/domains/identity-provider-attribute/subscriber.mjs.map +1 -1
  11. package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.d.ts +50 -0
  12. package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.d.ts.map +1 -0
  13. package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.mjs +86 -0
  14. package/dist/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.mjs.map +1 -0
  15. package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.d.ts +42 -0
  16. package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.d.ts.map +1 -0
  17. package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.mjs +80 -0
  18. package/dist/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.mjs.map +1 -0
  19. package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.d.ts.map +1 -1
  20. package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs +8 -2
  21. package/dist/adapters/http/adapters/oauth2/grant-types/refresh_token.mjs.map +1 -1
  22. package/dist/adapters/http/adapters/oauth2/grant-types/utils/credentials.mjs +1 -1
  23. package/dist/adapters/http/adapters/oauth2/grant-types/utils/guess.mjs +1 -1
  24. package/dist/adapters/http/controllers/entities/client/module.mjs +2 -2
  25. package/dist/adapters/http/controllers/entities/identity-provider/module.d.ts +24 -4
  26. package/dist/adapters/http/controllers/entities/identity-provider/module.d.ts.map +1 -1
  27. package/dist/adapters/http/controllers/entities/identity-provider/module.mjs +117 -106
  28. package/dist/adapters/http/controllers/entities/identity-provider/module.mjs.map +1 -1
  29. package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts +6 -4
  30. package/dist/adapters/http/controllers/entities/identity-provider/types.d.ts.map +1 -1
  31. package/dist/adapters/http/controllers/entities/realm/module.mjs +2 -2
  32. package/dist/adapters/http/controllers/entities/session/module.mjs +2 -2
  33. package/dist/adapters/http/controllers/entities/user/module.mjs +2 -2
  34. package/dist/adapters/http/controllers/entities/user-authenticator/module.mjs +2 -2
  35. package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.d.ts +2 -0
  36. package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.d.ts.map +1 -1
  37. package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.mjs +21 -3
  38. package/dist/adapters/http/controllers/workflows/authenticator-challenge/module.mjs.map +1 -1
  39. package/dist/adapters/http/controllers/workflows/authorize/module.d.ts.map +1 -1
  40. package/dist/adapters/http/controllers/workflows/authorize/module.mjs +14 -5
  41. package/dist/adapters/http/controllers/workflows/authorize/module.mjs.map +1 -1
  42. package/dist/adapters/http/controllers/workflows/token/module.d.ts.map +1 -1
  43. package/dist/adapters/http/controllers/workflows/token/module.mjs +22 -9
  44. package/dist/adapters/http/controllers/workflows/token/module.mjs.map +1 -1
  45. package/dist/adapters/http/controllers/workflows/token/utils/extract.mjs +2 -1
  46. package/dist/adapters/http/controllers/workflows/token/utils/extract.mjs.map +1 -1
  47. package/dist/adapters/http/middleware/built-in/assets.mjs +1 -1
  48. package/dist/adapters/http/middleware/built-in/cors.d.ts.map +1 -1
  49. package/dist/adapters/http/middleware/built-in/cors.mjs.map +1 -1
  50. package/dist/adapters/http/middleware/built-in/error.d.ts.map +1 -1
  51. package/dist/adapters/http/middleware/built-in/error.mjs +10 -1
  52. package/dist/adapters/http/middleware/built-in/error.mjs.map +1 -1
  53. package/dist/adapters/http/request/helpers/param-id.d.ts.map +1 -1
  54. package/dist/adapters/http/request/helpers/param-id.mjs +2 -1
  55. package/dist/adapters/http/request/helpers/param-id.mjs.map +1 -1
  56. package/dist/adapters/http/ui/account-console/module.mjs +1 -1
  57. package/dist/adapters/http/ui/auth-console/http-client.mjs +1 -1
  58. package/dist/adapters/http/ui/auth-console/module.mjs +1 -1
  59. package/dist/adapters/http/ui/console-packages/module.d.ts +1 -1
  60. package/dist/adapters/http/ui/console-packages/module.mjs +2 -2
  61. package/dist/adapters/http/ui/console-packages/module.mjs.map +1 -1
  62. package/dist/adapters/http/ui/shared/html.d.ts.map +1 -1
  63. package/dist/adapters/http/ui/shared/html.mjs +1 -0
  64. package/dist/adapters/http/ui/shared/html.mjs.map +1 -1
  65. package/dist/app/modules/config/normalize.d.ts.map +1 -1
  66. package/dist/app/modules/config/normalize.mjs +2 -2
  67. package/dist/app/modules/config/normalize.mjs.map +1 -1
  68. package/dist/app/modules/config/read/env.mjs +1 -1
  69. package/dist/app/modules/config/types.d.ts +8 -0
  70. package/dist/app/modules/config/types.d.ts.map +1 -1
  71. package/dist/app/modules/database/repositories/event/repository.d.ts +2 -2
  72. package/dist/app/modules/database/repositories/event/repository.d.ts.map +1 -1
  73. package/dist/app/modules/database/repositories/event/repository.mjs +23 -6
  74. package/dist/app/modules/database/repositories/event/repository.mjs.map +1 -1
  75. package/dist/app/modules/database/repositories/identity-provider/repository.d.ts +3 -1
  76. package/dist/app/modules/database/repositories/identity-provider/repository.d.ts.map +1 -1
  77. package/dist/app/modules/database/repositories/identity-provider/repository.mjs +2 -2
  78. package/dist/app/modules/database/repositories/identity-provider/repository.mjs.map +1 -1
  79. package/dist/app/modules/database/repositories/identity-provider-account/repository.d.ts.map +1 -1
  80. package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs +9 -1
  81. package/dist/app/modules/database/repositories/identity-provider-account/repository.mjs.map +1 -1
  82. package/dist/app/modules/http/modules/controller.d.ts.map +1 -1
  83. package/dist/app/modules/http/modules/controller.mjs +20 -6
  84. package/dist/app/modules/http/modules/controller.mjs.map +1 -1
  85. package/dist/app/modules/identity/module.d.ts.map +1 -1
  86. package/dist/app/modules/identity/module.mjs +6 -3
  87. package/dist/app/modules/identity/module.mjs.map +1 -1
  88. package/dist/app/modules/identity/repositories/user.d.ts +1 -0
  89. package/dist/app/modules/identity/repositories/user.d.ts.map +1 -1
  90. package/dist/app/modules/identity/repositories/user.mjs +3 -0
  91. package/dist/app/modules/identity/repositories/user.mjs.map +1 -1
  92. package/dist/app/modules/oauth2/constants.d.ts +2 -1
  93. package/dist/app/modules/oauth2/constants.d.ts.map +1 -1
  94. package/dist/app/modules/oauth2/constants.mjs +1 -0
  95. package/dist/app/modules/oauth2/constants.mjs.map +1 -1
  96. package/dist/app/modules/oauth2/module.d.ts.map +1 -1
  97. package/dist/app/modules/oauth2/module.mjs +5 -0
  98. package/dist/app/modules/oauth2/module.mjs.map +1 -1
  99. package/dist/app/modules/oauth2/repositories/authorize/state/repository.d.ts +1 -2
  100. package/dist/app/modules/oauth2/repositories/authorize/state/repository.d.ts.map +1 -1
  101. package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs +7 -16
  102. package/dist/app/modules/oauth2/repositories/authorize/state/repository.mjs.map +1 -1
  103. package/dist/app/modules/oauth2/repositories/constants.d.ts +1 -0
  104. package/dist/app/modules/oauth2/repositories/constants.d.ts.map +1 -1
  105. package/dist/app/modules/oauth2/repositories/constants.mjs +1 -0
  106. package/dist/app/modules/oauth2/repositories/constants.mjs.map +1 -1
  107. package/dist/app/modules/oauth2/repositories/federated-login/index.d.ts +2 -0
  108. package/dist/app/modules/oauth2/repositories/federated-login/index.d.ts.map +1 -0
  109. package/dist/app/modules/oauth2/repositories/federated-login/index.mjs +5 -0
  110. package/dist/app/modules/oauth2/repositories/federated-login/store.d.ts +9 -0
  111. package/dist/app/modules/oauth2/repositories/federated-login/store.d.ts.map +1 -0
  112. package/dist/app/modules/oauth2/repositories/federated-login/store.mjs +33 -0
  113. package/dist/app/modules/oauth2/repositories/federated-login/store.mjs.map +1 -0
  114. package/dist/app/modules/oauth2/repositories/index.d.ts +1 -0
  115. package/dist/app/modules/oauth2/repositories/index.d.ts.map +1 -1
  116. package/dist/app/modules/oauth2/repositories/index.mjs +3 -1
  117. package/dist/app/modules/runtime/module.mjs +2 -2
  118. package/dist/cli/commands/migration.mjs +1 -1
  119. package/dist/core/entities/client-scope/schema.d.ts.map +1 -1
  120. package/dist/core/entities/client-scope/schema.mjs +16 -1
  121. package/dist/core/entities/client-scope/schema.mjs.map +1 -1
  122. package/dist/core/entities/event/constants.d.ts +9 -0
  123. package/dist/core/entities/event/constants.d.ts.map +1 -1
  124. package/dist/core/entities/event/constants.mjs +9 -1
  125. package/dist/core/entities/event/constants.mjs.map +1 -1
  126. package/dist/core/entities/event/entity-event-handler.d.ts.map +1 -1
  127. package/dist/core/entities/event/entity-event-handler.mjs +14 -1
  128. package/dist/core/entities/event/entity-event-handler.mjs.map +1 -1
  129. package/dist/core/entities/event/index.mjs +2 -2
  130. package/dist/core/entities/event/types.d.ts +11 -2
  131. package/dist/core/entities/event/types.d.ts.map +1 -1
  132. package/dist/core/entities/identity-provider/types.d.ts +9 -1
  133. package/dist/core/entities/identity-provider/types.d.ts.map +1 -1
  134. package/dist/core/entities/identity-provider-account/types.d.ts +6 -0
  135. package/dist/core/entities/identity-provider-account/types.d.ts.map +1 -1
  136. package/dist/core/entities/identity-provider-account/types.mjs.map +1 -1
  137. package/dist/core/entities/index.mjs +2 -2
  138. package/dist/core/identity/entities/user/types.d.ts +1 -0
  139. package/dist/core/identity/entities/user/types.d.ts.map +1 -1
  140. package/dist/core/identity/index.mjs +12 -11
  141. package/dist/core/identity/provider/account/module.d.ts +3 -0
  142. package/dist/core/identity/provider/account/module.d.ts.map +1 -1
  143. package/dist/core/identity/provider/account/module.mjs +54 -27
  144. package/dist/core/identity/provider/account/module.mjs.map +1 -1
  145. package/dist/core/identity/provider/account/types.d.ts +7 -0
  146. package/dist/core/identity/provider/account/types.d.ts.map +1 -1
  147. package/dist/core/identity/provider/authentication/index.mjs +3 -2
  148. package/dist/core/identity/provider/authentication/protocols/index.mjs +2 -1
  149. package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.d.ts +46 -0
  150. package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.d.ts.map +1 -0
  151. package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs +89 -0
  152. package/dist/core/identity/provider/authentication/protocols/oauth2/assurance.mjs.map +1 -0
  153. package/dist/core/identity/provider/authentication/protocols/oauth2/index.d.ts +1 -0
  154. package/dist/core/identity/provider/authentication/protocols/oauth2/index.d.ts.map +1 -1
  155. package/dist/core/identity/provider/authentication/protocols/oauth2/index.mjs +2 -1
  156. package/dist/core/identity/provider/authentication/protocols/oauth2/module.d.ts.map +1 -1
  157. package/dist/core/identity/provider/authentication/protocols/oauth2/module.mjs +9 -2
  158. package/dist/core/identity/provider/authentication/protocols/oauth2/module.mjs.map +1 -1
  159. package/dist/core/identity/provider/index.mjs +12 -11
  160. package/dist/core/index.mjs +16 -12
  161. package/dist/core/oauth2/authorization/code-request/verifier/module.d.ts.map +1 -1
  162. package/dist/core/oauth2/authorization/code-request/verifier/module.mjs +7 -1
  163. package/dist/core/oauth2/authorization/code-request/verifier/module.mjs.map +1 -1
  164. package/dist/core/oauth2/authorization/helpers.d.ts.map +1 -1
  165. package/dist/core/oauth2/authorization/helpers.mjs +6 -1
  166. package/dist/core/oauth2/authorization/helpers.mjs.map +1 -1
  167. package/dist/core/oauth2/authorization/module.d.ts.map +1 -1
  168. package/dist/core/oauth2/authorization/module.mjs +5 -3
  169. package/dist/core/oauth2/authorization/module.mjs.map +1 -1
  170. package/dist/core/oauth2/authorization/state/module.mjs +1 -2
  171. package/dist/core/oauth2/authorization/state/module.mjs.map +1 -1
  172. package/dist/core/oauth2/authorization/state/types.d.ts +13 -2
  173. package/dist/core/oauth2/authorization/state/types.d.ts.map +1 -1
  174. package/dist/core/oauth2/end-session/service.d.ts.map +1 -1
  175. package/dist/core/oauth2/end-session/service.mjs +1 -0
  176. package/dist/core/oauth2/end-session/service.mjs.map +1 -1
  177. package/dist/core/oauth2/federated-login/constants.d.ts +22 -0
  178. package/dist/core/oauth2/federated-login/constants.d.ts.map +1 -0
  179. package/dist/core/oauth2/federated-login/constants.mjs +27 -0
  180. package/dist/core/oauth2/federated-login/constants.mjs.map +1 -0
  181. package/dist/core/oauth2/federated-login/index.d.ts +4 -0
  182. package/dist/core/oauth2/federated-login/index.d.ts.map +1 -0
  183. package/dist/core/oauth2/federated-login/index.mjs +7 -0
  184. package/dist/core/oauth2/federated-login/module.d.ts +29 -0
  185. package/dist/core/oauth2/federated-login/module.d.ts.map +1 -0
  186. package/dist/core/oauth2/federated-login/module.mjs +193 -0
  187. package/dist/core/oauth2/federated-login/module.mjs.map +1 -0
  188. package/dist/core/oauth2/federated-login/types.d.ts +196 -0
  189. package/dist/core/oauth2/federated-login/types.d.ts.map +1 -0
  190. package/dist/core/oauth2/federated-login/types.mjs +36 -0
  191. package/dist/core/oauth2/federated-login/types.mjs.map +1 -0
  192. package/dist/core/oauth2/grant-types/authorize.mjs +1 -1
  193. package/dist/core/oauth2/grant-types/client-credentials.mjs +1 -1
  194. package/dist/core/oauth2/grant-types/identity.mjs +1 -1
  195. package/dist/core/oauth2/grant-types/password.mjs +1 -1
  196. package/dist/core/oauth2/grant-types/refresh-token.mjs +1 -1
  197. package/dist/core/oauth2/index.d.ts +1 -0
  198. package/dist/core/oauth2/index.d.ts.map +1 -1
  199. package/dist/core/oauth2/index.mjs +5 -1
  200. package/dist/core/oauth2/token/verifier/module.d.ts.map +1 -1
  201. package/dist/core/oauth2/token/verifier/module.mjs +3 -3
  202. package/dist/core/oauth2/token/verifier/module.mjs.map +1 -1
  203. package/dist/core/provisioning/entities/policy/validator.d.ts.map +1 -1
  204. package/dist/core/provisioning/entities/policy/validator.mjs +2 -1
  205. package/dist/core/provisioning/entities/policy/validator.mjs.map +1 -1
  206. package/dist/core/provisioning/entities/realm/wildcard-validator.d.ts.map +1 -1
  207. package/dist/core/provisioning/entities/realm/wildcard-validator.mjs +2 -1
  208. package/dist/core/provisioning/entities/realm/wildcard-validator.mjs.map +1 -1
  209. package/dist/core/security/policy/evaluator.mjs.map +1 -1
  210. package/dist/node_modules/@ebec/core/dist/index.mjs +130 -0
  211. package/dist/node_modules/@ebec/core/dist/index.mjs.map +1 -0
  212. package/dist/swagger.json +119 -43
  213. package/dist/utils/error.d.ts.map +1 -1
  214. package/dist/utils/error.mjs +5 -6
  215. package/dist/utils/error.mjs.map +1 -1
  216. package/package.json +29 -29
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/client-scope/entity.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACR,MAAM,EACN,WAAW,EACX,KAAK,EACL,KAAK,EACR,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,qBAEa,iBAAkB,YAAW,WAAW;IAEjD,EAAE,EAAE,MAAM,CAAC;IAOX,OAAO,EAAE,OAAO,CAAC;IAKjB,SAAS,EAAE,MAAM,CAAC;IAGlB,SAAS,EAAE,MAAM,CAAC;IAKlB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAIvB,MAAM,EAAE,MAAM,CAAC;IAIf,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOlC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAMhC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAIrB,KAAK,EAAE,KAAK,CAAC;IAIb,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOjC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/client-scope/entity.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACR,MAAM,EACN,WAAW,EACX,KAAK,EACL,KAAK,EACR,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,qBAEa,iBAAkB,YAAW,WAAW;IAEjD,EAAE,EAAE,MAAM,CAAC;IAOX,OAAO,EAAE,OAAO,CAAC;IAMjB,SAAS,EAAE,MAAM,CAAC;IAIlB,SAAS,EAAE,MAAM,CAAC;IAKlB,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAIvB,MAAM,EAAE,MAAM,CAAC;IAIf,aAAa,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOlC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAMhC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAIrB,KAAK,EAAE,KAAK,CAAC;IAIb,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOjC,UAAU,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC"}
@@ -43,14 +43,22 @@ _ts_decorate([
43
43
  }),
44
44
  _ts_metadata("design:type", Boolean)
45
45
  ], ClientScopeEntity.prototype, "default", void 0);
46
- _ts_decorate([CreateDateColumn({
47
- name: "created_at",
48
- transformer: dateToISOStringTransformer
49
- }), _ts_metadata("design:type", String)], ClientScopeEntity.prototype, "createdAt", void 0);
50
- _ts_decorate([UpdateDateColumn({
51
- name: "updated_at",
52
- transformer: dateToISOStringTransformer
53
- }), _ts_metadata("design:type", String)], ClientScopeEntity.prototype, "updatedAt", void 0);
46
+ _ts_decorate([
47
+ Index(),
48
+ CreateDateColumn({
49
+ name: "created_at",
50
+ transformer: dateToISOStringTransformer
51
+ }),
52
+ _ts_metadata("design:type", String)
53
+ ], ClientScopeEntity.prototype, "createdAt", void 0);
54
+ _ts_decorate([
55
+ Index(),
56
+ UpdateDateColumn({
57
+ name: "updated_at",
58
+ transformer: dateToISOStringTransformer
59
+ }),
60
+ _ts_metadata("design:type", String)
61
+ ], ClientScopeEntity.prototype, "updatedAt", void 0);
54
62
  _ts_decorate([Column({ name: "client_id" }), _ts_metadata("design:type", Object)], ClientScopeEntity.prototype, "clientId", void 0);
55
63
  _ts_decorate([
56
64
  ManyToOne(() => ClientEntity, { onDelete: "CASCADE" }),
@@ -1 +1 @@
1
- {"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","Unique","UpdateDateColumn","dateToISOStringTransformer","ClientEntity","RealmEntity","ScopeEntity","ClientScopeEntity","id","default","createdAt","updatedAt","clientId","client","clientRealmId","clientRealm","scopeId","scope","scopeRealmId","scopeRealm","type","name","transformer","onDelete","nullable"],"sources":["../../../../../src/adapters/database/domains/client-scope/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n Unique,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n Client,\n ClientScope,\n Realm,\n Scope,\n} from '@authup/core-kit';\nimport { ClientEntity } from '../client/index.ts';\nimport { RealmEntity } from '../realm/index.ts';\nimport { ScopeEntity } from '../scope/index.ts';\n\n@Entity({ name: 'auth_client_scopes' })\n@Unique(['clientId', 'scopeId'])\nexport class ClientScopeEntity implements ClientScope {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n @Index()\n @Column({\n type: 'boolean',\n default: false, \n })\n default: boolean;\n\n // ------------------------------------------------------------------\n\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n\n // ------------------------------------------------------------------\n\n @Column({ name: 'client_id' })\n clientId: Client['id'];\n\n @ManyToOne(() => ClientEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'client_id' })\n client: Client;\n\n @Index()\n @Column({ name: 'client_realm_id', nullable: true })\n clientRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'client_realm_id' })\n clientRealm: RealmEntity | null;\n\n // ------------------------------------------------------------------\n\n @Index()\n @Column({ name: 'scope_id' })\n scopeId: Scope['id'];\n\n @ManyToOne(() => ScopeEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'scope_id' })\n scope: Scope;\n\n @Index()\n @Column({ name: 'scope_realm_id', nullable: true })\n scopeRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'scope_realm_id' })\n scopeRealm: RealmEntity | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAaa,oBAAb,MAAaA;CAETC;CAOAC;CAKAC;CAGAC;CAKAC;CAIAC;CAIAC;CAOAC;CAMAC;CAIAC;CAIAC;CAOAC;AACJ;;;;;EArDQC,MAAM;EACNX,SAAS;;;;;CAMOY,MAAM;CAAcC,aAAanB;;;CAGjCkB,MAAM;CAAcC,aAAanB;;AAK3CkB,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,YAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,kBAAA,WAAA,YAAA,KAAA,CAAA;;CAGCjB,gBAAAA,cAAAA,EAAgBmB,UAAU,UAAA,CAAA;CAC7BF,WAAAA,EAAAA,MAAM,YAAA,CAAA;;;;;;EAIVA,MAAM;EAAmBG,UAAU;;;;;CAG5BnB,gBAAAA,aAAAA;EACbkB,UAAU;EACVC,UAAU;;CAEAH,WAAAA,EAAAA,MAAM,kBAAA,CAAA;;;;;CAMVA,OAAAA,EAAAA,MAAM,WAAA,CAAA;;;;CAGCf,gBAAAA,aAAAA,EAAeiB,UAAU,UAAA,CAAA;CAC5BF,WAAAA,EAAAA,MAAM,WAAA,CAAA;;;;;;EAIVA,MAAM;EAAkBG,UAAU;;;;;CAG3BnB,gBAAAA,aAAAA;EACbkB,UAAU;EACVC,UAAU;;CAEAH,WAAAA,EAAAA,MAAM,iBAAA,CAAA;;;AA3DdA,oBAAAA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,qBAAA,CAAA,GAAA,OAAA,CACP,YAAY,SAAA,CAAA,CAAA,GAAA,iBAAA"}
1
+ {"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","Unique","UpdateDateColumn","dateToISOStringTransformer","ClientEntity","RealmEntity","ScopeEntity","ClientScopeEntity","id","default","createdAt","updatedAt","clientId","client","clientRealmId","clientRealm","scopeId","scope","scopeRealmId","scopeRealm","type","name","transformer","onDelete","nullable"],"sources":["../../../../../src/adapters/database/domains/client-scope/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2021-2021.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n Unique,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n Client,\n ClientScope,\n Realm,\n Scope,\n} from '@authup/core-kit';\nimport { ClientEntity } from '../client/index.ts';\nimport { RealmEntity } from '../realm/index.ts';\nimport { ScopeEntity } from '../scope/index.ts';\n\n@Entity({ name: 'auth_client_scopes' })\n@Unique(['clientId', 'scopeId'])\nexport class ClientScopeEntity implements ClientScope {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n @Index()\n @Column({\n type: 'boolean',\n default: false, \n })\n default: boolean;\n\n // ------------------------------------------------------------------\n\n @Index()\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @Index()\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n\n // ------------------------------------------------------------------\n\n @Column({ name: 'client_id' })\n clientId: Client['id'];\n\n @ManyToOne(() => ClientEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'client_id' })\n client: Client;\n\n @Index()\n @Column({ name: 'client_realm_id', nullable: true })\n clientRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'client_realm_id' })\n clientRealm: RealmEntity | null;\n\n // ------------------------------------------------------------------\n\n @Index()\n @Column({ name: 'scope_id' })\n scopeId: Scope['id'];\n\n @ManyToOne(() => ScopeEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'scope_id' })\n scope: Scope;\n\n @Index()\n @Column({ name: 'scope_realm_id', nullable: true })\n scopeRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'scope_realm_id' })\n scopeRealm: RealmEntity | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAaa,oBAAb,MAAaA;CAETC;CAOAC;CAMAC;CAIAC;CAKAC;CAIAC;CAIAC;CAOAC;CAMAC;CAIAC;CAIAC;CAOAC;AACJ;;;;;EAvDQC,MAAM;EACNX,SAAS;;;;;;;EAOOY,MAAM;EAAcC,aAAanB;;;;;;;EAIjCkB,MAAM;EAAcC,aAAanB;;;;AAK3CkB,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,YAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,kBAAA,WAAA,YAAA,KAAA,CAAA;;CAGCjB,gBAAAA,cAAAA,EAAgBmB,UAAU,UAAA,CAAA;CAC7BF,WAAAA,EAAAA,MAAM,YAAA,CAAA;;;;;;EAIVA,MAAM;EAAmBG,UAAU;;;;;CAG5BnB,gBAAAA,aAAAA;EACbkB,UAAU;EACVC,UAAU;;CAEAH,WAAAA,EAAAA,MAAM,kBAAA,CAAA;;;;;CAMVA,OAAAA,EAAAA,MAAM,WAAA,CAAA;;;;CAGCf,gBAAAA,aAAAA,EAAeiB,UAAU,UAAA,CAAA;CAC5BF,WAAAA,EAAAA,MAAM,WAAA,CAAA;;;;;;EAIVA,MAAM;EAAkBG,UAAU;;;;;CAG3BnB,gBAAAA,aAAAA;EACbkB,UAAU;EACVC,UAAU;;CAEAH,WAAAA,EAAAA,MAAM,iBAAA,CAAA;;;AA7DdA,oBAAAA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,qBAAA,CAAA,GAAA,OAAA,CACP,YAAY,SAAA,CAAA,CAAA,GAAA,iBAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/identity-provider-account/entity.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAER,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,EACL,IAAI,EACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,qBAGa,6BAA8B,YAAW,uBAAuB;IAEzE,EAAE,EAAE,MAAM,CAAC;IASX,WAAW,EAAE,MAAM,CAAC;IASpB,YAAY,EAAE,MAAM,CAAC;IAOrB,cAAc,EAAE,MAAM,CAAC;IASvB,gBAAgB,EAAE,MAAM,CAAC;IASzB,iBAAiB,EAAE,MAAM,CAAC;IAU1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAUzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAIzB,SAAS,EAAE,MAAM,CAAC;IAIlB,SAAS,EAAE,MAAM,CAAC;IAMlB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAInB,IAAI,EAAE,UAAU,CAAC;IAIjB,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOhC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAK9B,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAInC,QAAQ,EAAE,sBAAsB,CAAC;IAIjC,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOpC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC"}
1
+ {"version":3,"file":"entity.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/identity-provider-account/entity.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAER,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,EACL,IAAI,EACP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AAEvE,qBAMa,6BAA8B,YAAW,uBAAuB;IAEzE,EAAE,EAAE,MAAM,CAAC;IASX,WAAW,EAAE,MAAM,CAAC;IASpB,YAAY,EAAE,MAAM,CAAC;IAOrB,cAAc,EAAE,MAAM,CAAC;IASvB,gBAAgB,EAAE,MAAM,CAAC;IASzB,iBAAiB,EAAE,MAAM,CAAC;IAU1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAUzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAIzB,SAAS,EAAE,MAAM,CAAC;IAIlB,SAAS,EAAE,MAAM,CAAC;IAMlB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAInB,IAAI,EAAE,UAAU,CAAC;IAIjB,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOhC,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAK9B,UAAU,EAAE,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAInC,QAAQ,EAAE,sBAAsB,CAAC;IAIjC,eAAe,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAOpC,aAAa,EAAE,WAAW,GAAG,IAAI,CAAC;CACrC"}
@@ -157,7 +157,7 @@ _ts_decorate([
157
157
  IdentityProviderAccountEntity = _ts_decorate([
158
158
  Entity({ name: "auth_identity_provider_accounts" }),
159
159
  Index(["providerId", "userId"], { unique: true }),
160
- Index(["providerUserId", "providerId"])
160
+ Index(["providerUserId", "providerId"], { unique: true })
161
161
  ], IdentityProviderAccountEntity);
162
162
  //#endregion
163
163
  export { IdentityProviderAccountEntity };
@@ -1 +1 @@
1
- {"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","UpdateDateColumn","dateToISOStringTransformer","RealmEntity","UserEntity","IdentityProviderEntity","IdentityProviderAccountEntity","id","accessToken","refreshToken","providerUserId","providerUserName","providerUserEmail","expiresIn","expiresAt","createdAt","updatedAt","userId","user","userRealmId","userRealm","providerId","provider","providerRealmId","providerRealm","name","type","nullable","default","select","length","unsigned","transformer","onDelete","unique"],"sources":["../../../../../src/adapters/database/domains/identity-provider-account/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n \n IdentityProvider, \n IdentityProviderAccount, \n Realm, \n User, \n} from '@authup/core-kit';\nimport { RealmEntity } from '../realm/index.ts';\nimport { UserEntity } from '../user/index.ts';\nimport { IdentityProviderEntity } from '../identity-provider/index.ts';\n\n@Entity({ name: 'auth_identity_provider_accounts' })\n@Index(['providerId', 'userId'], { unique: true })\n@Index(['providerUserId', 'providerId'])\nexport class IdentityProviderAccountEntity implements IdentityProviderAccount {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n @Column({\n name: 'access_token',\n type: 'text',\n nullable: true,\n default: null,\n select: false,\n })\n accessToken: string;\n\n @Column({\n name: 'refresh_token',\n type: 'text',\n nullable: true,\n default: null,\n select: false,\n })\n refreshToken: string;\n\n @Column({\n name: 'provider_user_id', \n type: 'varchar', \n length: 256, \n })\n providerUserId: string;\n\n @Column({\n name: 'provider_user_name', \n type: 'varchar', \n length: 256, \n nullable: true, \n default: null, \n })\n providerUserName: string;\n\n @Column({\n name: 'provider_user_email', \n type: 'varchar', \n length: 512, \n nullable: true, \n default: null, \n })\n providerUserEmail: string;\n\n @Column({\n name: 'expires_in',\n type: 'int',\n unsigned: true,\n nullable: true,\n default: null,\n select: false,\n })\n expiresIn: number | null;\n\n @Column({\n name: 'expires_at',\n type: 'varchar',\n length: 28,\n nullable: true,\n default: null,\n select: false,\n })\n expiresAt: string | null;\n\n @Index()\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @Index()\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n\n // -----------------------------------------------\n\n @Index()\n @Column({ name: 'user_id' })\n userId: User['id'];\n\n @ManyToOne(() => UserEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'user_id' })\n user: UserEntity;\n\n @Index()\n @Column({ name: 'user_realm_id', nullable: true })\n userRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'user_realm_id' })\n userRealm: RealmEntity | null;\n\n // -----------------------------------------------\n\n @Column({ name: 'provider_id' })\n providerId: IdentityProvider['id'];\n\n @ManyToOne(() => IdentityProviderEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'provider_id' })\n provider: IdentityProviderEntity;\n\n @Index()\n @Column({ name: 'provider_realm_id', nullable: true })\n providerRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'provider_realm_id' })\n providerRealm: RealmEntity | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAaY,gCAAb,MAAaA;CAETC;CASAC;CASAC;CAOAC;CASAC;CASAC;CAUAC;CAUAC;CAIAC;CAIAC;CAMAC;CAIAC;CAIAC;CAOAC;CAKAC;CAIAC;CAIAC;CAOAC;AACJ;;;CA9GQC,MAAM;CACNC,MAAM;CACNC,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNC,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNI,QAAQ;;;CAKRL,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;;;CAKTH,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;;;CAKTH,MAAM;CACNC,MAAM;CACNK,UAAU;CACVJ,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;CACTC,QAAQ;;;;;EAKQJ,MAAM;EAAcO,aAAa9B;;;;;;;EAIjCuB,MAAM;EAAcO,aAAa9B;;;;;;CAM3CuB,OAAAA,EAAAA,MAAM,UAAA,CAAA;;;;CAGCrB,gBAAAA,YAAAA,EAAc6B,UAAU,UAAA,CAAA;CAC3BR,WAAAA,EAAAA,MAAM,UAAA,CAAA;;;;;;EAIVA,MAAM;EAAiBE,UAAU;;;;;CAG1BxB,gBAAAA,aAAAA;EACb8B,UAAU;EACVN,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,gBAAA,CAAA;;;AAKVA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,cAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,8BAAA,WAAA,cAAA,KAAA,CAAA;;CAGCpB,gBAAAA,wBAAAA,EAA0B4B,UAAU,UAAA,CAAA;CACvCR,WAAAA,EAAAA,MAAM,cAAA,CAAA;;;;;;EAIVA,MAAM;EAAqBE,UAAU;;;;;CAG9BxB,gBAAAA,aAAAA;EACb8B,UAAU;EACVN,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,oBAAA,CAAA;;;;CApHdA,OAAAA,EAAAA,MAAM,kCAAA,CAAA;CACR,MAAA,CAAA,cAAc,QAAA,GAAA,EAAaS,QAAQ,KAAA,CAAA;CACnC,MAAA,CAAA,kBAAkB,YAAA,CAAA"}
1
+ {"version":3,"file":"entity.mjs","names":["Column","CreateDateColumn","Entity","Index","JoinColumn","ManyToOne","PrimaryGeneratedColumn","UpdateDateColumn","dateToISOStringTransformer","RealmEntity","UserEntity","IdentityProviderEntity","IdentityProviderAccountEntity","id","accessToken","refreshToken","providerUserId","providerUserName","providerUserEmail","expiresIn","expiresAt","createdAt","updatedAt","userId","user","userRealmId","userRealm","providerId","provider","providerRealmId","providerRealm","name","type","nullable","default","select","length","unsigned","transformer","onDelete","unique"],"sources":["../../../../../src/adapters/database/domains/identity-provider-account/entity.ts"],"sourcesContent":["/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n JoinColumn,\n ManyToOne,\n PrimaryGeneratedColumn,\n UpdateDateColumn,\n} from 'typeorm';\nimport { dateToISOStringTransformer } from '../../helpers/index.ts';\nimport type {\n \n IdentityProvider, \n IdentityProviderAccount, \n Realm, \n User, \n} from '@authup/core-kit';\nimport { RealmEntity } from '../realm/index.ts';\nimport { UserEntity } from '../user/index.ts';\nimport { IdentityProviderEntity } from '../identity-provider/index.ts';\n\n@Entity({ name: 'auth_identity_provider_accounts' })\n@Index(['providerId', 'userId'], { unique: true })\n// one external identity belongs to one local user. The column order is\n// load-bearing: `providerUserId` leads the sequence the rapiq schema\n// declares, and reversing it would fail the boot-time index assertion.\n@Index(['providerUserId', 'providerId'], { unique: true })\nexport class IdentityProviderAccountEntity implements IdentityProviderAccount {\n @PrimaryGeneratedColumn('uuid')\n id: string;\n\n @Column({\n name: 'access_token',\n type: 'text',\n nullable: true,\n default: null,\n select: false,\n })\n accessToken: string;\n\n @Column({\n name: 'refresh_token',\n type: 'text',\n nullable: true,\n default: null,\n select: false,\n })\n refreshToken: string;\n\n @Column({\n name: 'provider_user_id', \n type: 'varchar', \n length: 256, \n })\n providerUserId: string;\n\n @Column({\n name: 'provider_user_name', \n type: 'varchar', \n length: 256, \n nullable: true, \n default: null, \n })\n providerUserName: string;\n\n @Column({\n name: 'provider_user_email', \n type: 'varchar', \n length: 512, \n nullable: true, \n default: null, \n })\n providerUserEmail: string;\n\n @Column({\n name: 'expires_in',\n type: 'int',\n unsigned: true,\n nullable: true,\n default: null,\n select: false,\n })\n expiresIn: number | null;\n\n @Column({\n name: 'expires_at',\n type: 'varchar',\n length: 28,\n nullable: true,\n default: null,\n select: false,\n })\n expiresAt: string | null;\n\n @Index()\n @CreateDateColumn({ name: 'created_at', transformer: dateToISOStringTransformer })\n createdAt: string;\n\n @Index()\n @UpdateDateColumn({ name: 'updated_at', transformer: dateToISOStringTransformer })\n updatedAt: string;\n\n // -----------------------------------------------\n\n @Index()\n @Column({ name: 'user_id' })\n userId: User['id'];\n\n @ManyToOne(() => UserEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'user_id' })\n user: UserEntity;\n\n @Index()\n @Column({ name: 'user_realm_id', nullable: true })\n userRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'user_realm_id' })\n userRealm: RealmEntity | null;\n\n // -----------------------------------------------\n\n @Column({ name: 'provider_id' })\n providerId: IdentityProvider['id'];\n\n @ManyToOne(() => IdentityProviderEntity, { onDelete: 'CASCADE' })\n @JoinColumn({ name: 'provider_id' })\n provider: IdentityProviderEntity;\n\n @Index()\n @Column({ name: 'provider_realm_id', nullable: true })\n providerRealmId: Realm['id'] | null;\n\n @ManyToOne(() => RealmEntity, {\n onDelete: 'CASCADE',\n nullable: true, \n })\n @JoinColumn({ name: 'provider_realm_id' })\n providerRealm: RealmEntity | null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmCA,IAAaY,gCAAb,MAAaA;CAETC;CASAC;CASAC;CAOAC;CASAC;CASAC;CAUAC;CAUAC;CAIAC;CAIAC;CAMAC;CAIAC;CAIAC;CAOAC;CAKAC;CAIAC;CAIAC;CAOAC;AACJ;;;CA9GQC,MAAM;CACNC,MAAM;CACNC,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNC,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNI,QAAQ;;;CAKRL,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;;;CAKTH,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;;;CAKTH,MAAM;CACNC,MAAM;CACNK,UAAU;CACVJ,UAAU;CACVC,SAAS;CACTC,QAAQ;;;CAKRJ,MAAM;CACNC,MAAM;CACNI,QAAQ;CACRH,UAAU;CACVC,SAAS;CACTC,QAAQ;;;;;EAKQJ,MAAM;EAAcO,aAAa9B;;;;;;;EAIjCuB,MAAM;EAAcO,aAAa9B;;;;;;CAM3CuB,OAAAA,EAAAA,MAAM,UAAA,CAAA;;;;CAGCrB,gBAAAA,YAAAA,EAAc6B,UAAU,UAAA,CAAA;CAC3BR,WAAAA,EAAAA,MAAM,UAAA,CAAA;;;;;;EAIVA,MAAM;EAAiBE,UAAU;;;;;CAG1BxB,gBAAAA,aAAAA;EACb8B,UAAU;EACVN,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,gBAAA,CAAA;;;AAKVA,aAAAA,CAAAA,OAAAA,EAAAA,MAAM,cAAA,CAAA,GAAA,aAAA,eAAA,MAAA,CAAA,GAAA,8BAAA,WAAA,cAAA,KAAA,CAAA;;CAGCpB,gBAAAA,wBAAAA,EAA0B4B,UAAU,UAAA,CAAA;CACvCR,WAAAA,EAAAA,MAAM,cAAA,CAAA;;;;;;EAIVA,MAAM;EAAqBE,UAAU;;;;;CAG9BxB,gBAAAA,aAAAA;EACb8B,UAAU;EACVN,UAAU;;CAEAF,WAAAA,EAAAA,MAAM,oBAAA,CAAA;;;;CAvHdA,OAAAA,EAAAA,MAAM,kCAAA,CAAA;CACR,MAAA,CAAA,cAAc,QAAA,GAAA,EAAaS,QAAQ,KAAA,CAAA;CAInC,MAAA,CAAA,kBAAkB,YAAA,GAAA,EAAiBA,QAAQ,KAAA,CAAA"}
@@ -1,6 +1,13 @@
1
- import type { IdentityProviderAttribute } from '@authup/core-kit';
1
+ import type { EntityDefaultEventName, IdentityProviderAttribute } from '@authup/core-kit';
2
2
  import { EntitySubscriber } from '../../subscriber/index.ts';
3
3
  export declare class IdentityProviderAttributeSubscriber extends EntitySubscriber<IdentityProviderAttribute> {
4
4
  constructor();
5
+ /**
6
+ * The row's `value` holds the provider's OAuth2 clientSecret or LDAP bind
7
+ * password, so it must never reach the realtime bus. Stripped on both
8
+ * sides: the previous payload is what an update would otherwise carry the
9
+ * OLD secret in.
10
+ */
11
+ protected publish(event: `${EntityDefaultEventName}`, data: IdentityProviderAttribute, dataPrevious?: IdentityProviderAttribute): Promise<void>;
5
12
  }
6
13
  //# sourceMappingURL=subscriber.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"subscriber.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/identity-provider-attribute/subscriber.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAIlE,OAAO,EAAE,gBAAgB,EAA2B,MAAM,2BAA2B,CAAC;AAItF,qBACa,mCAAoC,SAAQ,gBAAgB,CAAC,yBAAyB,CAAC;;CAgBnG"}
1
+ {"version":3,"file":"subscriber.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/domains/identity-provider-attribute/subscriber.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAC;AAI1F,OAAO,EAAE,gBAAgB,EAA2B,MAAM,2BAA2B,CAAC;AAItF,qBACa,mCAAoC,SAAQ,gBAAgB,CAAC,yBAAyB,CAAC;;IAiBhG;;;;;OAKG;cACsB,OAAO,CAC5B,KAAK,EAAE,GAAG,sBAAsB,EAAE,EAClC,IAAI,EAAE,yBAAyB,EAC/B,YAAY,CAAC,EAAE,yBAAyB,GACzC,OAAO,CAAC,IAAI,CAAC;CAOnB"}
@@ -30,6 +30,20 @@ var IdentityProviderAttributeSubscriber = class extends EntitySubscriber {
30
30
  })] }
31
31
  });
32
32
  }
33
+ /**
34
+ * The row's `value` holds the provider's OAuth2 clientSecret or LDAP bind
35
+ * password, so it must never reach the realtime bus. Stripped on both
36
+ * sides: the previous payload is what an update would otherwise carry the
37
+ * OLD secret in.
38
+ */ async publish(event, data, dataPrevious) {
39
+ await super.publish(event, {
40
+ ...data,
41
+ value: null
42
+ }, dataPrevious ? {
43
+ ...dataPrevious,
44
+ value: null
45
+ } : void 0);
46
+ }
33
47
  };
34
48
  IdentityProviderAttributeSubscriber = _ts_decorate([
35
49
  EventSubscriber(),
@@ -1 +1 @@
1
- {"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","IdentityProviderAttributeEntity","CachePrefix","IdentityProviderAttributeSubscriber","type","IDENTITY_PROVIDER_ATTRIBUTE","target","destinations","cache","keys","data","prefix","key","id"],"sources":["../../../../../src/adapters/database/domains/identity-provider-attribute/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IdentityProviderAttribute } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { IdentityProviderAttributeEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class IdentityProviderAttributeSubscriber extends EntitySubscriber<IdentityProviderAttribute> {\n constructor() {\n super({\n type: EntityType.IDENTITY_PROVIDER_ATTRIBUTE,\n target: IdentityProviderAttributeEntity,\n destinations: buildEntityDestinations(EntityType.IDENTITY_PROVIDER_ATTRIBUTE),\n cache: {\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.IDENTITY_PROVIDER_ATTRIBUTE,\n key: data.id,\n }),\n ],\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,sCAAb,cAAyDJ,iBAAAA;CACrD,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,2BAA2B;GAC5EG,OAAO,EACHC,OAAOC,SAAS,CACZb,kBAAkB;IACdc,QAAQT,YAAYG;IACpBO,KAAKF,KAAKG;GACd,CAAA,CACH,EACL;EACJ,CAAA;CACJ;AACJ"}
1
+ {"version":3,"file":"subscriber.mjs","names":["EntityType","buildRedisKeyPath","EventSubscriber","EntitySubscriber","buildEntityDestinations","IdentityProviderAttributeEntity","CachePrefix","IdentityProviderAttributeSubscriber","type","IDENTITY_PROVIDER_ATTRIBUTE","target","destinations","cache","keys","data","prefix","key","id","publish","event","dataPrevious","value","undefined"],"sources":["../../../../../src/adapters/database/domains/identity-provider-attribute/subscriber.ts"],"sourcesContent":["/*\n * Copyright (c) 2022-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { EntityDefaultEventName, IdentityProviderAttribute } from '@authup/core-kit';\nimport { EntityType } from '@authup/core-kit';\nimport { buildRedisKeyPath } from '@authup/server-kit';\nimport { EventSubscriber } from 'typeorm';\nimport { EntitySubscriber, buildEntityDestinations } from '../../subscriber/index.ts';\nimport { IdentityProviderAttributeEntity } from './entity.ts';\nimport { CachePrefix } from '../constants.ts';\n\n@EventSubscriber()\nexport class IdentityProviderAttributeSubscriber extends EntitySubscriber<IdentityProviderAttribute> {\n constructor() {\n super({\n type: EntityType.IDENTITY_PROVIDER_ATTRIBUTE,\n target: IdentityProviderAttributeEntity,\n destinations: buildEntityDestinations(EntityType.IDENTITY_PROVIDER_ATTRIBUTE),\n cache: {\n keys: (data) => [\n buildRedisKeyPath({\n prefix: CachePrefix.IDENTITY_PROVIDER_ATTRIBUTE,\n key: data.id,\n }),\n ],\n },\n });\n }\n\n /**\n * The row's `value` holds the provider's OAuth2 clientSecret or LDAP bind\n * password, so it must never reach the realtime bus. Stripped on both\n * sides: the previous payload is what an update would otherwise carry the\n * OLD secret in.\n */\n protected override async publish(\n event: `${EntityDefaultEventName}`,\n data: IdentityProviderAttribute,\n dataPrevious?: IdentityProviderAttribute,\n ): Promise<void> {\n await super.publish(\n event,\n { ...data, value: null },\n dataPrevious ? { ...dataPrevious, value: null } : undefined,\n );\n }\n}\n"],"mappings":";;;;;;;;;;;AAKC,SAAA,aAAA,YAAA,QAAA,KAAA,MAAA;;;;;;;;;AAWD,IAAaO,sCAAb,cAAyDJ,iBAAAA;CACrD,cAAc;EACV,MAAM;GACFK,MAAMR,WAAWS;GACjBC,QAAQL;GACRM,cAAcP,wBAAwBJ,WAAWS,2BAA2B;GAC5EG,OAAO,EACHC,OAAOC,SAAS,CACZb,kBAAkB;IACdc,QAAQT,YAAYG;IACpBO,KAAKF,KAAKG;GACd,CAAA,CACH,EACL;EACJ,CAAA;CACJ;;;;;;IAQA,MAAyBC,QACrBC,OACAL,MACAM,cACa;EACb,MAAM,MAAMF,QACRC,OACA;GAAE,GAAGL;GAAMO,OAAO;EAAK,GACvBD,eAAe;GAAE,GAAGA;GAAcC,OAAO;EAAK,IAAIC,KAAAA,CAAAA;CAE1D;AACJ"}
@@ -0,0 +1,50 @@
1
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
2
+ /**
3
+ * Client-scope sort indexes (issue #3441) and identity-provider account
4
+ * uniqueness (issue #3442).
5
+ *
6
+ * - Indexes `auth_client_scopes.created_at` and `updated_at`.
7
+ * `clientScopeSchema` was the only registered schema with no `sorts`
8
+ * allow-list, so rapiq fell back to a syntactic name check and handed an
9
+ * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires
10
+ * every listed key to lead a real entity index; the two timestamp columns
11
+ * were the only ones missing theirs.
12
+ * - Makes `(provider_user_id, provider_id)` unique on
13
+ * `auth_identity_provider_accounts`. "One external identity belongs to one
14
+ * local user" was enforced only by a read-then-write in
15
+ * `IdentityProviderAccountManager`: no transaction, no row lock, and
16
+ * nothing behind it in the schema, so two concurrent completions for the
17
+ * same upstream subject could both observe "not linked" and both insert.
18
+ * After that the subject resolves to whichever row the database happens to
19
+ * order first. The column order matches the pre-existing non-unique index,
20
+ * so this is an in-place uniqueness flip under the same derived name
21
+ * rather than a rename.
22
+ *
23
+ * MySQL commits DDL implicitly, so `migrationsTransactionMode: 'all'` cannot
24
+ * roll a partial run back. A DROP followed by a CREATE would leave the table
25
+ * with no index of that name if the process died between them, and every
26
+ * later attempt would then fail at the DROP. One ALTER carrying both is
27
+ * atomic, so the uniqueness flip either applies or does not.
28
+ *
29
+ * Pre-existing duplicates abort the boot with an actionable message. They
30
+ * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the
31
+ * check only decides whether the operator reads a readable sentence or a
32
+ * hash-named driver error.
33
+ *
34
+ * It runs BEFORE any DDL for the same implicit-commit reason: an abort
35
+ * after the two CREATE INDEX statements leaves them committed while the
36
+ * migration stays unapplied, so the operator's retry — after cleaning the
37
+ * duplicates — would die on `Duplicate key name` and never reach the flip.
38
+ * Nothing here writes before the check, so a refusal leaves the schema
39
+ * exactly as it was.
40
+ *
41
+ * Generated with `migration generate`; derived IDX_<hash> names, generated
42
+ * DDL untouched (the duplicate pre-check and the single-ALTER flip are
43
+ * hand-authored).
44
+ */
45
+ export declare class SortIndexesAndAccountUniqueness1786631686318 implements MigrationInterface {
46
+ name: string;
47
+ up(queryRunner: QueryRunner): Promise<void>;
48
+ down(queryRunner: QueryRunner): Promise<void>;
49
+ }
50
+ //# sourceMappingURL=1786631686318-SortIndexesAndAccountUniqueness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1786631686318-SortIndexesAndAccountUniqueness.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,qBAAa,4CAA6C,YAAW,kBAAkB;IACnF,IAAI,SAAkD;IAEzC,EAAE,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B3C,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAa7D"}
@@ -0,0 +1,86 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ //#region src/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.ts
5
+ /**
6
+ * Client-scope sort indexes (issue #3441) and identity-provider account
7
+ * uniqueness (issue #3442).
8
+ *
9
+ * - Indexes `auth_client_scopes.created_at` and `updated_at`.
10
+ * `clientScopeSchema` was the only registered schema with no `sorts`
11
+ * allow-list, so rapiq fell back to a syntactic name check and handed an
12
+ * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires
13
+ * every listed key to lead a real entity index; the two timestamp columns
14
+ * were the only ones missing theirs.
15
+ * - Makes `(provider_user_id, provider_id)` unique on
16
+ * `auth_identity_provider_accounts`. "One external identity belongs to one
17
+ * local user" was enforced only by a read-then-write in
18
+ * `IdentityProviderAccountManager`: no transaction, no row lock, and
19
+ * nothing behind it in the schema, so two concurrent completions for the
20
+ * same upstream subject could both observe "not linked" and both insert.
21
+ * After that the subject resolves to whichever row the database happens to
22
+ * order first. The column order matches the pre-existing non-unique index,
23
+ * so this is an in-place uniqueness flip under the same derived name
24
+ * rather than a rename.
25
+ *
26
+ * MySQL commits DDL implicitly, so `migrationsTransactionMode: 'all'` cannot
27
+ * roll a partial run back. A DROP followed by a CREATE would leave the table
28
+ * with no index of that name if the process died between them, and every
29
+ * later attempt would then fail at the DROP. One ALTER carrying both is
30
+ * atomic, so the uniqueness flip either applies or does not.
31
+ *
32
+ * Pre-existing duplicates abort the boot with an actionable message. They
33
+ * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the
34
+ * check only decides whether the operator reads a readable sentence or a
35
+ * hash-named driver error.
36
+ *
37
+ * It runs BEFORE any DDL for the same implicit-commit reason: an abort
38
+ * after the two CREATE INDEX statements leaves them committed while the
39
+ * migration stays unapplied, so the operator's retry — after cleaning the
40
+ * duplicates — would die on `Duplicate key name` and never reach the flip.
41
+ * Nothing here writes before the check, so a refusal leaves the schema
42
+ * exactly as it was.
43
+ *
44
+ * Generated with `migration generate`; derived IDX_<hash> names, generated
45
+ * DDL untouched (the duplicate pre-check and the single-ALTER flip are
46
+ * hand-authored).
47
+ */ var SortIndexesAndAccountUniqueness1786631686318 = class {
48
+ name = "SortIndexesAndAccountUniqueness1786631686318";
49
+ async up(queryRunner) {
50
+ const duplicates = await queryRunner.query(`
51
+ SELECT \`provider_id\`, \`provider_user_id\`, COUNT(*) AS \`count\`
52
+ FROM \`auth_identity_provider_accounts\`
53
+ GROUP BY \`provider_id\`, \`provider_user_id\`
54
+ HAVING COUNT(*) > 1
55
+ `);
56
+ if (duplicates.length > 0) throw new Error(`Identity-provider account uniqueness migration aborted: "auth_identity_provider_accounts" holds ${duplicates.length} duplicate (provider_id, provider_user_id) group(s). One external identity must belong to one local user. Merge or delete the conflicting rows manually before re-running.`);
57
+ await queryRunner.query(`
58
+ CREATE INDEX \`IDX_52f59535945c8cdbd62439bba5\` ON \`auth_client_scopes\` (\`created_at\`)
59
+ `);
60
+ await queryRunner.query(`
61
+ CREATE INDEX \`IDX_04264aebc8b6625b1da88e23df\` ON \`auth_client_scopes\` (\`updated_at\`)
62
+ `);
63
+ await queryRunner.query(`
64
+ ALTER TABLE \`auth_identity_provider_accounts\`
65
+ DROP INDEX \`IDX_ccf3fd36253755bd9a5f43c516\`,
66
+ ADD UNIQUE INDEX \`IDX_ccf3fd36253755bd9a5f43c516\` (\`provider_user_id\`, \`provider_id\`)
67
+ `);
68
+ }
69
+ async down(queryRunner) {
70
+ await queryRunner.query(`
71
+ ALTER TABLE \`auth_identity_provider_accounts\`
72
+ DROP INDEX \`IDX_ccf3fd36253755bd9a5f43c516\`,
73
+ ADD INDEX \`IDX_ccf3fd36253755bd9a5f43c516\` (\`provider_user_id\`, \`provider_id\`)
74
+ `);
75
+ await queryRunner.query(`
76
+ DROP INDEX \`IDX_04264aebc8b6625b1da88e23df\` ON \`auth_client_scopes\`
77
+ `);
78
+ await queryRunner.query(`
79
+ DROP INDEX \`IDX_52f59535945c8cdbd62439bba5\` ON \`auth_client_scopes\`
80
+ `);
81
+ }
82
+ };
83
+ //#endregion
84
+ export { SortIndexesAndAccountUniqueness1786631686318 };
85
+
86
+ //# sourceMappingURL=1786631686318-SortIndexesAndAccountUniqueness.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1786631686318-SortIndexesAndAccountUniqueness.mjs","names":["SortIndexesAndAccountUniqueness1786631686318","name","up","queryRunner","duplicates","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/mysql/1786631686318-SortIndexesAndAccountUniqueness.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Client-scope sort indexes (issue #3441) and identity-provider account\n * uniqueness (issue #3442).\n *\n * - Indexes `auth_client_scopes.created_at` and `updated_at`.\n * `clientScopeSchema` was the only registered schema with no `sorts`\n * allow-list, so rapiq fell back to a syntactic name check and handed an\n * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires\n * every listed key to lead a real entity index; the two timestamp columns\n * were the only ones missing theirs.\n * - Makes `(provider_user_id, provider_id)` unique on\n * `auth_identity_provider_accounts`. \"One external identity belongs to one\n * local user\" was enforced only by a read-then-write in\n * `IdentityProviderAccountManager`: no transaction, no row lock, and\n * nothing behind it in the schema, so two concurrent completions for the\n * same upstream subject could both observe \"not linked\" and both insert.\n * After that the subject resolves to whichever row the database happens to\n * order first. The column order matches the pre-existing non-unique index,\n * so this is an in-place uniqueness flip under the same derived name\n * rather than a rename.\n *\n * MySQL commits DDL implicitly, so `migrationsTransactionMode: 'all'` cannot\n * roll a partial run back. A DROP followed by a CREATE would leave the table\n * with no index of that name if the process died between them, and every\n * later attempt would then fail at the DROP. One ALTER carrying both is\n * atomic, so the uniqueness flip either applies or does not.\n *\n * Pre-existing duplicates abort the boot with an actionable message. They\n * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the\n * check only decides whether the operator reads a readable sentence or a\n * hash-named driver error.\n *\n * It runs BEFORE any DDL for the same implicit-commit reason: an abort\n * after the two CREATE INDEX statements leaves them committed while the\n * migration stays unapplied, so the operator's retry — after cleaning the\n * duplicates — would die on `Duplicate key name` and never reach the flip.\n * Nothing here writes before the check, so a refusal leaves the schema\n * exactly as it was.\n *\n * Generated with `migration generate`; derived IDX_<hash> names, generated\n * DDL untouched (the duplicate pre-check and the single-ALTER flip are\n * hand-authored).\n */\nexport class SortIndexesAndAccountUniqueness1786631686318 implements MigrationInterface {\n name = 'SortIndexesAndAccountUniqueness1786631686318';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n const duplicates = await queryRunner.query(`\n SELECT \\`provider_id\\`, \\`provider_user_id\\`, COUNT(*) AS \\`count\\`\n FROM \\`auth_identity_provider_accounts\\`\n GROUP BY \\`provider_id\\`, \\`provider_user_id\\`\n HAVING COUNT(*) > 1\n `);\n if (duplicates.length > 0) {\n throw new Error(\n `Identity-provider account uniqueness migration aborted: \"auth_identity_provider_accounts\" holds ${duplicates.length} ` +\n 'duplicate (provider_id, provider_user_id) group(s). One external identity must belong to one local user. ' +\n 'Merge or delete the conflicting rows manually before re-running.',\n );\n }\n\n await queryRunner.query(`\n CREATE INDEX \\`IDX_52f59535945c8cdbd62439bba5\\` ON \\`auth_client_scopes\\` (\\`created_at\\`)\n `);\n await queryRunner.query(`\n CREATE INDEX \\`IDX_04264aebc8b6625b1da88e23df\\` ON \\`auth_client_scopes\\` (\\`updated_at\\`)\n `);\n\n await queryRunner.query(`\n ALTER TABLE \\`auth_identity_provider_accounts\\`\n DROP INDEX \\`IDX_ccf3fd36253755bd9a5f43c516\\`,\n ADD UNIQUE INDEX \\`IDX_ccf3fd36253755bd9a5f43c516\\` (\\`provider_user_id\\`, \\`provider_id\\`)\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n ALTER TABLE \\`auth_identity_provider_accounts\\`\n DROP INDEX \\`IDX_ccf3fd36253755bd9a5f43c516\\`,\n ADD INDEX \\`IDX_ccf3fd36253755bd9a5f43c516\\` (\\`provider_user_id\\`, \\`provider_id\\`)\n `);\n await queryRunner.query(`\n DROP INDEX \\`IDX_04264aebc8b6625b1da88e23df\\` ON \\`auth_client_scopes\\`\n `);\n await queryRunner.query(`\n DROP INDEX \\`IDX_52f59535945c8cdbd62439bba5\\` ON \\`auth_client_scopes\\`\n `);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CA,IAAaA,+CAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EACrD,MAAMC,aAAa,MAAMD,YAAYE,MAAM;;;;;SAK1C;EACD,IAAID,WAAWE,SAAS,GACpB,MAAM,IAAIC,MACN,mGAAmGH,WAAWE,OAAO,2KAErH;EAIR,MAAMH,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;EAED,MAAMF,YAAYE,MAAM;;;;SAIvB;CACL;CAEA,MAAaG,KAAKL,aAAyC;EACvD,MAAMA,YAAYE,MAAM;;;;SAIvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;CACL;AACJ"}
@@ -0,0 +1,42 @@
1
+ import type { MigrationInterface, QueryRunner } from 'typeorm';
2
+ /**
3
+ * Client-scope sort indexes (issue #3441) and identity-provider account
4
+ * uniqueness (issue #3442).
5
+ *
6
+ * - Indexes `auth_client_scopes.created_at` and `updated_at`.
7
+ * `clientScopeSchema` was the only registered schema with no `sorts`
8
+ * allow-list, so rapiq fell back to a syntactic name check and handed an
9
+ * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires
10
+ * every listed key to lead a real entity index; the two timestamp columns
11
+ * were the only ones missing theirs.
12
+ * - Makes `(provider_user_id, provider_id)` unique on
13
+ * `auth_identity_provider_accounts`. "One external identity belongs to one
14
+ * local user" was enforced only by a read-then-write in
15
+ * `IdentityProviderAccountManager`: no transaction, no row lock, and
16
+ * nothing behind it in the schema, so two concurrent completions for the
17
+ * same upstream subject could both observe "not linked" and both insert.
18
+ * After that the subject resolves to whichever row the database happens to
19
+ * order first. The column order matches the pre-existing non-unique index,
20
+ * so this is an in-place uniqueness flip under the same derived name
21
+ * rather than a rename.
22
+ *
23
+ * Pre-existing duplicates abort the boot with an actionable message. They
24
+ * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the
25
+ * check only decides whether the operator reads a readable sentence or a
26
+ * hash-named driver error.
27
+ *
28
+ * It runs before any DDL, matching the mysql half: postgres would roll the
29
+ * whole migration back on the abort, but keeping one order across both
30
+ * dialects means the refusal never depends on which one is reading it.
31
+ *
32
+ * Generated with `migration generate`; derived IDX_<hash> names, generated
33
+ * DDL untouched (the duplicate pre-check is hand-authored, and `down()`
34
+ * carries the hand-corrected column order — see
35
+ * .agents/references/typeorm.md).
36
+ */
37
+ export declare class SortIndexesAndAccountUniqueness1786631686318 implements MigrationInterface {
38
+ name: string;
39
+ up(queryRunner: QueryRunner): Promise<void>;
40
+ down(queryRunner: QueryRunner): Promise<void>;
41
+ }
42
+ //# sourceMappingURL=1786631686318-SortIndexesAndAccountUniqueness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1786631686318-SortIndexesAndAccountUniqueness.d.ts","sourceRoot":"","sources":["../../../../../src/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,4CAA6C,YAAW,kBAAkB;IACnF,IAAI,SAAkD;IAEzC,EAAE,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C,IAAI,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;CAc7D"}
@@ -0,0 +1,80 @@
1
+ import "node:path";
2
+ import "node:url";
3
+ import.meta.url;
4
+ //#region src/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.ts
5
+ /**
6
+ * Client-scope sort indexes (issue #3441) and identity-provider account
7
+ * uniqueness (issue #3442).
8
+ *
9
+ * - Indexes `auth_client_scopes.created_at` and `updated_at`.
10
+ * `clientScopeSchema` was the only registered schema with no `sorts`
11
+ * allow-list, so rapiq fell back to a syntactic name check and handed an
12
+ * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires
13
+ * every listed key to lead a real entity index; the two timestamp columns
14
+ * were the only ones missing theirs.
15
+ * - Makes `(provider_user_id, provider_id)` unique on
16
+ * `auth_identity_provider_accounts`. "One external identity belongs to one
17
+ * local user" was enforced only by a read-then-write in
18
+ * `IdentityProviderAccountManager`: no transaction, no row lock, and
19
+ * nothing behind it in the schema, so two concurrent completions for the
20
+ * same upstream subject could both observe "not linked" and both insert.
21
+ * After that the subject resolves to whichever row the database happens to
22
+ * order first. The column order matches the pre-existing non-unique index,
23
+ * so this is an in-place uniqueness flip under the same derived name
24
+ * rather than a rename.
25
+ *
26
+ * Pre-existing duplicates abort the boot with an actionable message. They
27
+ * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the
28
+ * check only decides whether the operator reads a readable sentence or a
29
+ * hash-named driver error.
30
+ *
31
+ * It runs before any DDL, matching the mysql half: postgres would roll the
32
+ * whole migration back on the abort, but keeping one order across both
33
+ * dialects means the refusal never depends on which one is reading it.
34
+ *
35
+ * Generated with `migration generate`; derived IDX_<hash> names, generated
36
+ * DDL untouched (the duplicate pre-check is hand-authored, and `down()`
37
+ * carries the hand-corrected column order — see
38
+ * .agents/references/typeorm.md).
39
+ */ var SortIndexesAndAccountUniqueness1786631686318 = class {
40
+ name = "SortIndexesAndAccountUniqueness1786631686318";
41
+ async up(queryRunner) {
42
+ const duplicates = await queryRunner.query(`
43
+ SELECT "provider_id", "provider_user_id", COUNT(*) AS "count"
44
+ FROM "auth_identity_provider_accounts"
45
+ GROUP BY "provider_id", "provider_user_id"
46
+ HAVING COUNT(*) > 1
47
+ `);
48
+ if (duplicates.length > 0) throw new Error(`Identity-provider account uniqueness migration aborted: "auth_identity_provider_accounts" holds ${duplicates.length} duplicate (provider_id, provider_user_id) group(s). One external identity must belong to one local user. Merge or delete the conflicting rows manually before re-running.`);
49
+ await queryRunner.query(`
50
+ CREATE INDEX "IDX_52f59535945c8cdbd62439bba5" ON "auth_client_scopes" ("created_at")
51
+ `);
52
+ await queryRunner.query(`
53
+ CREATE INDEX "IDX_04264aebc8b6625b1da88e23df" ON "auth_client_scopes" ("updated_at")
54
+ `);
55
+ await queryRunner.query(`
56
+ DROP INDEX "public"."IDX_ccf3fd36253755bd9a5f43c516"
57
+ `);
58
+ await queryRunner.query(`
59
+ CREATE UNIQUE INDEX "IDX_ccf3fd36253755bd9a5f43c516" ON "auth_identity_provider_accounts" ("provider_user_id", "provider_id")
60
+ `);
61
+ }
62
+ async down(queryRunner) {
63
+ await queryRunner.query(`
64
+ DROP INDEX "public"."IDX_ccf3fd36253755bd9a5f43c516"
65
+ `);
66
+ await queryRunner.query(`
67
+ CREATE INDEX "IDX_ccf3fd36253755bd9a5f43c516" ON "auth_identity_provider_accounts" ("provider_user_id", "provider_id")
68
+ `);
69
+ await queryRunner.query(`
70
+ DROP INDEX "public"."IDX_04264aebc8b6625b1da88e23df"
71
+ `);
72
+ await queryRunner.query(`
73
+ DROP INDEX "public"."IDX_52f59535945c8cdbd62439bba5"
74
+ `);
75
+ }
76
+ };
77
+ //#endregion
78
+ export { SortIndexesAndAccountUniqueness1786631686318 };
79
+
80
+ //# sourceMappingURL=1786631686318-SortIndexesAndAccountUniqueness.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"1786631686318-SortIndexesAndAccountUniqueness.mjs","names":["SortIndexesAndAccountUniqueness1786631686318","name","up","queryRunner","duplicates","query","length","Error","down"],"sources":["../../../../../src/adapters/database/migrations/postgres/1786631686318-SortIndexesAndAccountUniqueness.ts"],"sourcesContent":["import type { MigrationInterface, QueryRunner } from 'typeorm';\n\n/**\n * Client-scope sort indexes (issue #3441) and identity-provider account\n * uniqueness (issue #3442).\n *\n * - Indexes `auth_client_scopes.created_at` and `updated_at`.\n * `clientScopeSchema` was the only registered schema with no `sorts`\n * allow-list, so rapiq fell back to a syntactic name check and handed an\n * arbitrary `?sort=` key to `ORDER BY`. Declaring the allow-list requires\n * every listed key to lead a real entity index; the two timestamp columns\n * were the only ones missing theirs.\n * - Makes `(provider_user_id, provider_id)` unique on\n * `auth_identity_provider_accounts`. \"One external identity belongs to one\n * local user\" was enforced only by a read-then-write in\n * `IdentityProviderAccountManager`: no transaction, no row lock, and\n * nothing behind it in the schema, so two concurrent completions for the\n * same upstream subject could both observe \"not linked\" and both insert.\n * After that the subject resolves to whichever row the database happens to\n * order first. The column order matches the pre-existing non-unique index,\n * so this is an in-place uniqueness flip under the same derived name\n * rather than a rename.\n *\n * Pre-existing duplicates abort the boot with an actionable message. They\n * would abort it anyway, since `CREATE UNIQUE INDEX` fails on them; the\n * check only decides whether the operator reads a readable sentence or a\n * hash-named driver error.\n *\n * It runs before any DDL, matching the mysql half: postgres would roll the\n * whole migration back on the abort, but keeping one order across both\n * dialects means the refusal never depends on which one is reading it.\n *\n * Generated with `migration generate`; derived IDX_<hash> names, generated\n * DDL untouched (the duplicate pre-check is hand-authored, and `down()`\n * carries the hand-corrected column order — see\n * .agents/references/typeorm.md).\n */\nexport class SortIndexesAndAccountUniqueness1786631686318 implements MigrationInterface {\n name = 'SortIndexesAndAccountUniqueness1786631686318';\n\n public async up(queryRunner: QueryRunner): Promise<void> {\n const duplicates = await queryRunner.query(`\n SELECT \"provider_id\", \"provider_user_id\", COUNT(*) AS \"count\"\n FROM \"auth_identity_provider_accounts\"\n GROUP BY \"provider_id\", \"provider_user_id\"\n HAVING COUNT(*) > 1\n `);\n if (duplicates.length > 0) {\n throw new Error(\n `Identity-provider account uniqueness migration aborted: \"auth_identity_provider_accounts\" holds ${duplicates.length} ` +\n 'duplicate (provider_id, provider_user_id) group(s). One external identity must belong to one local user. ' +\n 'Merge or delete the conflicting rows manually before re-running.',\n );\n }\n\n await queryRunner.query(`\n CREATE INDEX \"IDX_52f59535945c8cdbd62439bba5\" ON \"auth_client_scopes\" (\"created_at\")\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_04264aebc8b6625b1da88e23df\" ON \"auth_client_scopes\" (\"updated_at\")\n `);\n\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_ccf3fd36253755bd9a5f43c516\"\n `);\n await queryRunner.query(`\n CREATE UNIQUE INDEX \"IDX_ccf3fd36253755bd9a5f43c516\" ON \"auth_identity_provider_accounts\" (\"provider_user_id\", \"provider_id\")\n `);\n }\n\n public async down(queryRunner: QueryRunner): Promise<void> {\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_ccf3fd36253755bd9a5f43c516\"\n `);\n await queryRunner.query(`\n CREATE INDEX \"IDX_ccf3fd36253755bd9a5f43c516\" ON \"auth_identity_provider_accounts\" (\"provider_user_id\", \"provider_id\")\n `);\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_04264aebc8b6625b1da88e23df\"\n `);\n await queryRunner.query(`\n DROP INDEX \"public\".\"IDX_52f59535945c8cdbd62439bba5\"\n `);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCA,IAAaA,+CAAb,MAAaA;CACTC,OAAO;CAEP,MAAaC,GAAGC,aAAyC;EACrD,MAAMC,aAAa,MAAMD,YAAYE,MAAM;;;;;SAK1C;EACD,IAAID,WAAWE,SAAS,GACpB,MAAM,IAAIC,MACN,mGAAmGH,WAAWE,OAAO,2KAErH;EAIR,MAAMH,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;EAED,MAAMF,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;CACL;CAEA,MAAaG,KAAKL,aAAyC;EACvD,MAAMA,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;EACD,MAAMF,YAAYE,MAAM;;SAEvB;CACL;AACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"refresh_token.d.ts","sourceRoot":"","sources":["../../../../../../src/adapters/http/adapters/oauth2/grant-types/refresh_token.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAA2B,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAGvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAA4B,MAAM,8BAA8B,CAAC;AACjG,OAAO,KAAK,EACR,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,kCAAkC,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAOnE,qBAAa,2BAA4B,SAAQ,uBAAwB,YAAW,gBAAgB;IAChG,SAAS,CAAC,mBAAmB,EAAG,yBAAyB,CAAC;IAE1D,SAAS,CAAC,oBAAoB,EAAG,oBAAoB,CAAC;IAEtD,SAAS,CAAC,eAAe,EAAG,gBAAgB,CAAC;IAE7C,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;gBAEnC,GAAG,EAAE,kCAAkC;IAS7C,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,wBAAwB,CAAC;CAqG5E"}
1
+ {"version":3,"file":"refresh_token.d.ts","sourceRoot":"","sources":["../../../../../../src/adapters/http/adapters/oauth2/grant-types/refresh_token.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAA2B,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAQvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAE,uBAAuB,EAA4B,MAAM,8BAA8B,CAAC;AACjG,OAAO,KAAK,EACR,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,kCAAkC,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACvF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAOnE,qBAAa,2BAA4B,SAAQ,uBAAwB,YAAW,gBAAgB;IAChG,SAAS,CAAC,mBAAmB,EAAG,yBAAyB,CAAC;IAE1D,SAAS,CAAC,oBAAoB,EAAG,oBAAoB,CAAC;IAEtD,SAAS,CAAC,eAAe,EAAG,gBAAgB,CAAC;IAE7C,SAAS,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;gBAEnC,GAAG,EAAE,kCAAkC;IAS7C,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,wBAAwB,CAAC;CAqH5E"}
@@ -9,7 +9,7 @@ import { extractClientCredentialsFromRequest } from "./utils/credentials.mjs";
9
9
  import { readRealmHint } from "./utils/realm.mjs";
10
10
  import "./utils/index.mjs";
11
11
  import { isClientPublic } from "@authup/core-kit";
12
- import { OAuth2GrantError, OAuth2RequestError, OAuth2TokenGrant } from "@authup/specs";
12
+ import { OAuth2GrantError, OAuth2RequestError, OAuth2TokenGrant, isJWTError } from "@authup/specs";
13
13
  import { getRequestHeader, getRequestIP } from "routup";
14
14
  import { readRequestBody } from "@routup/basic/body";
15
15
  //#region src/adapters/http/adapters/oauth2/grant-types/refresh_token.ts
@@ -31,7 +31,13 @@ var HTTPOAuth2RefreshTokenGrant = class extends OAuth2RefreshTokenGrant {
31
31
  if (typeof refreshToken !== "string" || refreshToken.length === 0) throw OAuth2RequestError.malformed();
32
32
  const { clientId, clientSecret } = await extractClientCredentialsFromRequest(event);
33
33
  const certificateEvidence = await extractOAuth2ClientCertificateEvidence(event, this.certificateSource);
34
- const payload = await this.refreshTokenVerifier.verify(refreshToken, { skipActiveCheck: true });
34
+ let payload;
35
+ try {
36
+ payload = await this.refreshTokenVerifier.verify(refreshToken, { skipActiveCheck: true });
37
+ } catch (e) {
38
+ if (isJWTError(e)) throw OAuth2GrantError.invalid();
39
+ throw e;
40
+ }
35
41
  let client;
36
42
  if (clientId) {
37
43
  const realm = await this.realmRepository.resolve(readRealmHint(body), true);
@@ -1 +1 @@
1
- {"version":3,"file":"refresh_token.mjs","names":["isClientPublic","OAuth2GrantError","OAuth2RequestError","OAuth2TokenGrant","readRequestBody","getRequestHeader","getRequestIP","OAuth2RefreshTokenGrant","assertClientGrantAllowed","extractClientCredentialsFromRequest","extractOAuth2ClientCertificateEvidence","readRealmHint","HTTPOAuth2RefreshTokenGrant","clientAuthenticator","refreshTokenVerifier","realmRepository","certificateSource","ctx","tokenVerifier","runWithRequest","event","body","refreshToken","refresh_token","length","malformed","clientId","clientSecret","certificateEvidence","payload","verify","skipActiveCheck","client","realm","resolve","authenticate","id","client_id","invalid","undefined","REFRESH_TOKEN","confirmation","cnf","expectedThumbprint","validateCertificateEvidenceForBinding","resolveTokenBinding","realm_id","realmId","runWith","ipAddress","userAgent"],"sources":["../../../../../../src/adapters/http/adapters/oauth2/grant-types/refresh_token.ts"],"sourcesContent":["/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { type Client, isClientPublic } from '@authup/core-kit';\nimport type { OAuth2TokenConfirmation, OAuth2TokenGrantResponse } from '@authup/specs';\nimport { OAuth2GrantError, OAuth2RequestError, OAuth2TokenGrant } from '@authup/specs';\nimport { readRequestBody } from '@routup/basic/body';\nimport type { IAppEvent } from 'routup';\nimport { getRequestHeader, getRequestIP } from 'routup';\nimport { OAuth2RefreshTokenGrant, assertClientGrantAllowed } from '../../../../../core/index.ts';\nimport type {\n IOAuth2TokenVerifier,\n IRealmRepository,\n OAuth2ClientAuthenticator,\n} from '../../../../../core/index.ts';\nimport type { HTTPOAuth2RefreshTokenGrantContext, IHTTPOAuth2Grant } from './types.ts';\nimport type { CertificateSource } from '../../../request/index.ts';\nimport {\n extractClientCredentialsFromRequest,\n extractOAuth2ClientCertificateEvidence,\n readRealmHint,\n} from './utils/index.ts';\n\nexport class HTTPOAuth2RefreshTokenGrant extends OAuth2RefreshTokenGrant implements IHTTPOAuth2Grant {\n protected clientAuthenticator : OAuth2ClientAuthenticator;\n\n protected refreshTokenVerifier : IOAuth2TokenVerifier;\n\n protected realmRepository : IRealmRepository;\n\n protected certificateSource: CertificateSource;\n\n constructor(ctx: HTTPOAuth2RefreshTokenGrantContext) {\n super(ctx);\n\n this.clientAuthenticator = ctx.clientAuthenticator;\n this.refreshTokenVerifier = ctx.tokenVerifier;\n this.realmRepository = ctx.realmRepository;\n this.certificateSource = ctx.certificateSource ?? 'disabled';\n }\n\n async runWithRequest(event: IAppEvent): Promise<OAuth2TokenGrantResponse> {\n const body = await readRequestBody(event);\n const refreshToken = body?.refresh_token;\n if (typeof refreshToken !== 'string' || refreshToken.length === 0) {\n throw OAuth2RequestError.malformed();\n }\n\n const { clientId, clientSecret } = await extractClientCredentialsFromRequest(event);\n const certificateEvidence = await extractOAuth2ClientCertificateEvidence(event, this.certificateSource);\n\n // RFC 6749 §6: verify the refresh token first to learn its bound\n // client (if any), then enforce binding. Authenticate the requesting\n // client when credentials are present, or when the token requires\n // a client binding.\n //\n // skipActiveCheck: the durable auth_session_tokens row (not the cache\n // blocklist) is the refresh-token authority, so a replayed/consumed\n // token must reach runWith() to trigger family revocation instead of\n // being rejected here with JWT_INACTIVE.\n const payload = await this.refreshTokenVerifier.verify(refreshToken, { skipActiveCheck: true });\n\n let client: Client | undefined;\n\n if (clientId) {\n // A client authenticated itself. Resolve by the presented\n // id/secret (name resolution scoped by the realm hint — resolved\n // lazily so a bare refresh skips the SELECT) and enforce the\n // token↔client binding.\n const realm = await this.realmRepository.resolve(readRealmHint(body), true);\n\n client = await this.clientAuthenticator.authenticate(\n clientId,\n clientSecret,\n realm.id,\n certificateEvidence,\n );\n\n if (payload.client_id && payload.client_id !== client.id) {\n throw OAuth2GrantError.invalid();\n }\n } else if (payload.client_id) {\n // No client credentials were presented, but the token is bound to\n // a client. RFC 6749 §10.4: a public client cannot authenticate\n // (no secret) and is not required to — the bound identity is read\n // from the signed token (client_id is server-minted, so trusted)\n // and refresh-token rotation/replay detection is the abuse control.\n // A client with an authentication method MUST still authenticate.\n // Supplying the server-minted client id lets TLS clients prove\n // themselves with the request certificate, while a secret client\n // still fails because its secret is absent.\n client = await this.clientAuthenticator.authenticate(\n payload.client_id,\n undefined,\n undefined,\n certificateEvidence,\n );\n }\n\n if (client) {\n assertClientGrantAllowed(client, OAuth2TokenGrant.REFRESH_TOKEN);\n }\n\n let confirmation: OAuth2TokenConfirmation | undefined;\n if (payload.cnf) {\n const expectedThumbprint = payload.cnf['x5t#S256'];\n if (typeof expectedThumbprint !== 'string' || expectedThumbprint.length === 0) {\n throw OAuth2GrantError.invalid();\n }\n\n confirmation = this.clientAuthenticator.validateCertificateEvidenceForBinding(\n certificateEvidence,\n );\n if (confirmation['x5t#S256'] !== expectedThumbprint) {\n throw OAuth2GrantError.invalid();\n }\n } else if (client) {\n confirmation = this.clientAuthenticator.resolveTokenBinding(client, certificateEvidence);\n }\n\n // Realm parity for PUBLIC clients only: a public client may not refresh\n // a token whose realm differs from the (bound) client's own realm.\n // Kills cross-realm refresh tokens minted for a public `web` client\n // before the authorize-side realm gate existed. Authenticated clients\n // are exempt — the configured secret/certificate proves identity, and the\n // documented cross-realm password grant (UUID-identified user against a\n // master-realm client) depends on that exemption.\n if (\n client &&\n isClientPublic(client) &&\n payload.realm_id &&\n payload.realm_id !== client.realmId\n ) {\n throw OAuth2GrantError.invalid();\n }\n\n return this.runWith(payload, {\n confirmation,\n ipAddress: getRequestIP(event) ?? undefined,\n userAgent: getRequestHeader(event, 'user-agent') ?? undefined,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA2BA,IAAaY,8BAAb,cAAiDL,wBAAAA;CACnCM;CAEAC;CAEAC;CAEAC;CAEV,YAAYC,KAAyC;EACjD,MAAMA,GAAAA;EAEN,KAAKJ,sBAAsBI,IAAIJ;EAC/B,KAAKC,uBAAuBG,IAAIC;EAChC,KAAKH,kBAAkBE,IAAIF;EAC3B,KAAKC,oBAAoBC,IAAID,qBAAqB;CACtD;CAEA,MAAMG,eAAeC,OAAqD;EACtE,MAAMC,OAAO,MAAMjB,gBAAgBgB,KAAAA;EACnC,MAAME,eAAeD,MAAME;EAC3B,IAAI,OAAOD,iBAAiB,YAAYA,aAAaE,WAAW,GAC5D,MAAMtB,mBAAmBuB,UAAS;EAGtC,MAAM,EAAEC,UAAUC,iBAAiB,MAAMlB,oCAAoCW,KAAAA;EAC7E,MAAMQ,sBAAsB,MAAMlB,uCAAuCU,OAAO,KAAKJ,iBAAiB;EAWtG,MAAMa,UAAU,MAAM,KAAKf,qBAAqBgB,OAAOR,cAAc,EAAES,iBAAiB,KAAK,CAAA;EAE7F,IAAIC;EAEJ,IAAIN,UAAU;GAKV,MAAMO,QAAQ,MAAM,KAAKlB,gBAAgBmB,QAAQvB,cAAcU,IAAAA,GAAO,IAAA;GAEtEW,SAAS,MAAM,KAAKnB,oBAAoBsB,aACpCT,UACAC,cACAM,MAAMG,IACNR,mBAAAA;GAGJ,IAAIC,QAAQQ,aAAaR,QAAQQ,cAAcL,OAAOI,IAClD,MAAMnC,iBAAiBqC,QAAO;EAEtC,OAAO,IAAIT,QAAQQ,WAUfL,SAAS,MAAM,KAAKnB,oBAAoBsB,aACpCN,QAAQQ,WACRE,KAAAA,GACAA,KAAAA,GACAX,mBAAAA;EAIR,IAAII,QACAxB,yBAAyBwB,QAAQ7B,iBAAiBqC,aAAa;EAGnE,IAAIC;EACJ,IAAIZ,QAAQa,KAAK;GACb,MAAMC,qBAAqBd,QAAQa,IAAI;GACvC,IAAI,OAAOC,uBAAuB,YAAYA,mBAAmBnB,WAAW,GACxE,MAAMvB,iBAAiBqC,QAAO;GAGlCG,eAAe,KAAK5B,oBAAoB+B,sCACpChB,mBAAAA;GAEJ,IAAIa,aAAa,gBAAgBE,oBAC7B,MAAM1C,iBAAiBqC,QAAO;EAEtC,OAAO,IAAIN,QACPS,eAAe,KAAK5B,oBAAoBgC,oBAAoBb,QAAQJ,mBAAAA;EAUxE,IACII,UACAhC,eAAegC,MAAAA,KACfH,QAAQiB,YACRjB,QAAQiB,aAAad,OAAOe,SAE5B,MAAM9C,iBAAiBqC,QAAO;EAGlC,OAAO,KAAKU,QAAQnB,SAAS;GACzBY;GACAQ,WAAW3C,aAAac,KAAAA,KAAUmB,KAAAA;GAClCW,WAAW7C,iBAAiBe,OAAO,YAAA,KAAiBmB,KAAAA;EACxD,CAAA;CACJ;AACJ"}
1
+ {"version":3,"file":"refresh_token.mjs","names":["isClientPublic","OAuth2GrantError","OAuth2RequestError","OAuth2TokenGrant","isJWTError","readRequestBody","getRequestHeader","getRequestIP","OAuth2RefreshTokenGrant","assertClientGrantAllowed","extractClientCredentialsFromRequest","extractOAuth2ClientCertificateEvidence","readRealmHint","HTTPOAuth2RefreshTokenGrant","clientAuthenticator","refreshTokenVerifier","realmRepository","certificateSource","ctx","tokenVerifier","runWithRequest","event","body","refreshToken","refresh_token","length","malformed","clientId","clientSecret","certificateEvidence","payload","verify","skipActiveCheck","e","invalid","client","realm","resolve","authenticate","id","client_id","undefined","REFRESH_TOKEN","confirmation","cnf","expectedThumbprint","validateCertificateEvidenceForBinding","resolveTokenBinding","realm_id","realmId","runWith","ipAddress","userAgent"],"sources":["../../../../../../src/adapters/http/adapters/oauth2/grant-types/refresh_token.ts"],"sourcesContent":["/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { type Client, isClientPublic } from '@authup/core-kit';\nimport type { OAuth2TokenConfirmation, OAuth2TokenGrantResponse } from '@authup/specs';\nimport {\n OAuth2GrantError,\n OAuth2RequestError,\n OAuth2TokenGrant,\n isJWTError,\n} from '@authup/specs';\nimport { readRequestBody } from '@routup/basic/body';\nimport type { IAppEvent } from 'routup';\nimport { getRequestHeader, getRequestIP } from 'routup';\nimport { OAuth2RefreshTokenGrant, assertClientGrantAllowed } from '../../../../../core/index.ts';\nimport type {\n IOAuth2TokenVerifier,\n IRealmRepository,\n OAuth2ClientAuthenticator,\n} from '../../../../../core/index.ts';\nimport type { HTTPOAuth2RefreshTokenGrantContext, IHTTPOAuth2Grant } from './types.ts';\nimport type { CertificateSource } from '../../../request/index.ts';\nimport {\n extractClientCredentialsFromRequest,\n extractOAuth2ClientCertificateEvidence,\n readRealmHint,\n} from './utils/index.ts';\n\nexport class HTTPOAuth2RefreshTokenGrant extends OAuth2RefreshTokenGrant implements IHTTPOAuth2Grant {\n protected clientAuthenticator : OAuth2ClientAuthenticator;\n\n protected refreshTokenVerifier : IOAuth2TokenVerifier;\n\n protected realmRepository : IRealmRepository;\n\n protected certificateSource: CertificateSource;\n\n constructor(ctx: HTTPOAuth2RefreshTokenGrantContext) {\n super(ctx);\n\n this.clientAuthenticator = ctx.clientAuthenticator;\n this.refreshTokenVerifier = ctx.tokenVerifier;\n this.realmRepository = ctx.realmRepository;\n this.certificateSource = ctx.certificateSource ?? 'disabled';\n }\n\n async runWithRequest(event: IAppEvent): Promise<OAuth2TokenGrantResponse> {\n const body = await readRequestBody(event);\n const refreshToken = body?.refresh_token;\n if (typeof refreshToken !== 'string' || refreshToken.length === 0) {\n throw OAuth2RequestError.malformed();\n }\n\n const { clientId, clientSecret } = await extractClientCredentialsFromRequest(event);\n const certificateEvidence = await extractOAuth2ClientCertificateEvidence(event, this.certificateSource);\n\n // RFC 6749 §6: verify the refresh token first to learn its bound\n // client (if any), then enforce binding. Authenticate the requesting\n // client when credentials are present, or when the token requires\n // a client binding.\n //\n // skipActiveCheck: the durable auth_session_tokens row (not the cache\n // blocklist) is the refresh-token authority, so a replayed/consumed\n // token must reach runWith() to trigger family revocation instead of\n // being rejected here with JWT_INACTIVE.\n let payload : Awaited<ReturnType<typeof this.refreshTokenVerifier.verify>>;\n try {\n payload = await this.refreshTokenVerifier.verify(refreshToken, { skipActiveCheck: true });\n } catch (e) {\n // RFC 6749 §5.2: a refresh token the endpoint cannot accept is\n // `invalid_grant` (400). A verification failure raises a JWT\n // error, which answers 401 on a resource route (RFC 6750 §3.1),\n // and letting that status escape here would report a bad GRANT\n // as if the CLIENT had failed to authenticate. The branches\n // below already answer `invalid_grant` for a token bound to\n // another client, so this keeps one shape for the parameter.\n if (isJWTError(e)) {\n throw OAuth2GrantError.invalid();\n }\n\n throw e;\n }\n\n let client: Client | undefined;\n\n if (clientId) {\n // A client authenticated itself. Resolve by the presented\n // id/secret (name resolution scoped by the realm hint — resolved\n // lazily so a bare refresh skips the SELECT) and enforce the\n // token↔client binding.\n const realm = await this.realmRepository.resolve(readRealmHint(body), true);\n\n client = await this.clientAuthenticator.authenticate(\n clientId,\n clientSecret,\n realm.id,\n certificateEvidence,\n );\n\n if (payload.client_id && payload.client_id !== client.id) {\n throw OAuth2GrantError.invalid();\n }\n } else if (payload.client_id) {\n // No client credentials were presented, but the token is bound to\n // a client. RFC 6749 §10.4: a public client cannot authenticate\n // (no secret) and is not required to — the bound identity is read\n // from the signed token (client_id is server-minted, so trusted)\n // and refresh-token rotation/replay detection is the abuse control.\n // A client with an authentication method MUST still authenticate.\n // Supplying the server-minted client id lets TLS clients prove\n // themselves with the request certificate, while a secret client\n // still fails because its secret is absent.\n client = await this.clientAuthenticator.authenticate(\n payload.client_id,\n undefined,\n undefined,\n certificateEvidence,\n );\n }\n\n if (client) {\n assertClientGrantAllowed(client, OAuth2TokenGrant.REFRESH_TOKEN);\n }\n\n let confirmation: OAuth2TokenConfirmation | undefined;\n if (payload.cnf) {\n const expectedThumbprint = payload.cnf['x5t#S256'];\n if (typeof expectedThumbprint !== 'string' || expectedThumbprint.length === 0) {\n throw OAuth2GrantError.invalid();\n }\n\n confirmation = this.clientAuthenticator.validateCertificateEvidenceForBinding(\n certificateEvidence,\n );\n if (confirmation['x5t#S256'] !== expectedThumbprint) {\n throw OAuth2GrantError.invalid();\n }\n } else if (client) {\n confirmation = this.clientAuthenticator.resolveTokenBinding(client, certificateEvidence);\n }\n\n // Realm parity for PUBLIC clients only: a public client may not refresh\n // a token whose realm differs from the (bound) client's own realm.\n // Kills cross-realm refresh tokens minted for a public `web` client\n // before the authorize-side realm gate existed. Authenticated clients\n // are exempt — the configured secret/certificate proves identity, and the\n // documented cross-realm password grant (UUID-identified user against a\n // master-realm client) depends on that exemption.\n if (\n client &&\n isClientPublic(client) &&\n payload.realm_id &&\n payload.realm_id !== client.realmId\n ) {\n throw OAuth2GrantError.invalid();\n }\n\n return this.runWith(payload, {\n confirmation,\n ipAddress: getRequestIP(event) ?? undefined,\n userAgent: getRequestHeader(event, 'user-agent') ?? undefined,\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgCA,IAAaa,8BAAb,cAAiDL,wBAAAA;CACnCM;CAEAC;CAEAC;CAEAC;CAEV,YAAYC,KAAyC;EACjD,MAAMA,GAAAA;EAEN,KAAKJ,sBAAsBI,IAAIJ;EAC/B,KAAKC,uBAAuBG,IAAIC;EAChC,KAAKH,kBAAkBE,IAAIF;EAC3B,KAAKC,oBAAoBC,IAAID,qBAAqB;CACtD;CAEA,MAAMG,eAAeC,OAAqD;EACtE,MAAMC,OAAO,MAAMjB,gBAAgBgB,KAAAA;EACnC,MAAME,eAAeD,MAAME;EAC3B,IAAI,OAAOD,iBAAiB,YAAYA,aAAaE,WAAW,GAC5D,MAAMvB,mBAAmBwB,UAAS;EAGtC,MAAM,EAAEC,UAAUC,iBAAiB,MAAMlB,oCAAoCW,KAAAA;EAC7E,MAAMQ,sBAAsB,MAAMlB,uCAAuCU,OAAO,KAAKJ,iBAAiB;EAWtG,IAAIa;EACJ,IAAI;GACAA,UAAU,MAAM,KAAKf,qBAAqBgB,OAAOR,cAAc,EAAES,iBAAiB,KAAK,CAAA;EAC3F,SAASC,GAAG;GAQR,IAAI7B,WAAW6B,CAAAA,GACX,MAAMhC,iBAAiBiC,QAAO;GAGlC,MAAMD;EACV;EAEA,IAAIE;EAEJ,IAAIR,UAAU;GAKV,MAAMS,QAAQ,MAAM,KAAKpB,gBAAgBqB,QAAQzB,cAAcU,IAAAA,GAAO,IAAA;GAEtEa,SAAS,MAAM,KAAKrB,oBAAoBwB,aACpCX,UACAC,cACAQ,MAAMG,IACNV,mBAAAA;GAGJ,IAAIC,QAAQU,aAAaV,QAAQU,cAAcL,OAAOI,IAClD,MAAMtC,iBAAiBiC,QAAO;EAEtC,OAAO,IAAIJ,QAAQU,WAUfL,SAAS,MAAM,KAAKrB,oBAAoBwB,aACpCR,QAAQU,WACRC,KAAAA,GACAA,KAAAA,GACAZ,mBAAAA;EAIR,IAAIM,QACA1B,yBAAyB0B,QAAQhC,iBAAiBuC,aAAa;EAGnE,IAAIC;EACJ,IAAIb,QAAQc,KAAK;GACb,MAAMC,qBAAqBf,QAAQc,IAAI;GACvC,IAAI,OAAOC,uBAAuB,YAAYA,mBAAmBpB,WAAW,GACxE,MAAMxB,iBAAiBiC,QAAO;GAGlCS,eAAe,KAAK7B,oBAAoBgC,sCACpCjB,mBAAAA;GAEJ,IAAIc,aAAa,gBAAgBE,oBAC7B,MAAM5C,iBAAiBiC,QAAO;EAEtC,OAAO,IAAIC,QACPQ,eAAe,KAAK7B,oBAAoBiC,oBAAoBZ,QAAQN,mBAAAA;EAUxE,IACIM,UACAnC,eAAemC,MAAAA,KACfL,QAAQkB,YACRlB,QAAQkB,aAAab,OAAOc,SAE5B,MAAMhD,iBAAiBiC,QAAO;EAGlC,OAAO,KAAKgB,QAAQpB,SAAS;GACzBa;GACAQ,WAAW5C,aAAac,KAAAA,KAAUoB,KAAAA;GAClCW,WAAW9C,iBAAiBe,OAAO,YAAA,KAAiBoB,KAAAA;EACxD,CAAA;CACJ;AACJ"}
@@ -2,8 +2,8 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { OAuth2RequestError } from "@authup/specs";
5
- import { readRequestBody } from "@routup/basic/body";
6
5
  import { AuthorizationHeaderType, parseAuthorizationHeader } from "hapic";
6
+ import { readRequestBody } from "@routup/basic/body";
7
7
  //#region src/adapters/http/adapters/oauth2/grant-types/utils/credentials.ts
8
8
  /**
9
9
  * Extract client credentials from an OAuth2 token endpoint request.
@@ -2,9 +2,9 @@ import "node:path";
2
2
  import "node:url";
3
3
  import.meta.url;
4
4
  import { OAuth2TokenGrant } from "@authup/specs";
5
+ import { AuthorizationHeaderType, parseAuthorizationHeader } from "hapic";
5
6
  import { readRequestBody } from "@routup/basic/body";
6
7
  import { useRequestQuery } from "@routup/basic/query";
7
- import { AuthorizationHeaderType, parseAuthorizationHeader } from "hapic";
8
8
  //#region src/adapters/http/adapters/oauth2/grant-types/utils/guess.ts
9
9
  async function guessOauth2GrantTypeByRequest(event) {
10
10
  const body = await readRequestBody(event);
@@ -3,6 +3,8 @@ import "node:url";
3
3
  import.meta.url;
4
4
  import { RECORD_QUERY_PARAMETERS, describeQuerySchema } from "../../../../../core/query/describe.mjs";
5
5
  import { clientSchema } from "../../../../../core/entities/client/schema.mjs";
6
+ import { isSelfToken } from "../../../../../utils/self-id.mjs";
7
+ import "../../../../../utils/index.mjs";
6
8
  import { OAuth2ScopeAttributesResolver } from "../../../../../core/oauth2/scope/resolver.mjs";
7
9
  import "../../../../../core/index.mjs";
8
10
  import { useRequestIdentity } from "../../../request/helpers/identity.mjs";
@@ -11,8 +13,6 @@ import { applyRouteRealmIDToBody, getRequestRealmID } from "../../../request/hel
11
13
  import { useRequestScopes } from "../../../request/helpers/scopes.mjs";
12
14
  import "../../../request/index.mjs";
13
15
  import { ForceLoggedInMiddleware } from "../../../middleware/built-in/loggedin/module.mjs";
14
- import { isSelfToken } from "../../../../../utils/self-id.mjs";
15
- import "../../../../../utils/index.mjs";
16
16
  import "../../../middleware/index.mjs";
17
17
  import { EntityNotFoundError } from "@authup/errors";
18
18
  import { OAuth2SubKind } from "@authup/specs";