@atproto/pds 0.4.165 → 0.4.166

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 (282) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/account-manager/account-manager.js +2 -2
  3. package/dist/account-manager/account-manager.js.map +1 -1
  4. package/dist/account-manager/helpers/account-device.d.ts +4 -4
  5. package/dist/account-manager/helpers/account.d.ts +1 -1
  6. package/dist/account-manager/helpers/auth.d.ts +1 -1
  7. package/dist/account-manager/helpers/auth.d.ts.map +1 -1
  8. package/dist/account-manager/helpers/auth.js +8 -8
  9. package/dist/account-manager/helpers/auth.js.map +1 -1
  10. package/dist/account-manager/helpers/authorization-request.d.ts +1 -1
  11. package/dist/account-manager/helpers/authorization-request.d.ts.map +1 -1
  12. package/dist/account-manager/helpers/authorization-request.js +16 -8
  13. package/dist/account-manager/helpers/authorization-request.js.map +1 -1
  14. package/dist/account-manager/helpers/token.d.ts +65 -65
  15. package/dist/actor-store/preference/reader.d.ts +2 -2
  16. package/dist/actor-store/preference/reader.d.ts.map +1 -1
  17. package/dist/actor-store/preference/reader.js +2 -2
  18. package/dist/actor-store/preference/reader.js.map +1 -1
  19. package/dist/actor-store/preference/transactor.d.ts +2 -2
  20. package/dist/actor-store/preference/transactor.d.ts.map +1 -1
  21. package/dist/actor-store/preference/transactor.js +5 -5
  22. package/dist/actor-store/preference/transactor.js.map +1 -1
  23. package/dist/actor-store/preference/util.d.ts +4 -2
  24. package/dist/actor-store/preference/util.d.ts.map +1 -1
  25. package/dist/actor-store/preference/util.js +9 -8
  26. package/dist/actor-store/preference/util.js.map +1 -1
  27. package/dist/actor-store/record/reader.d.ts +2 -2
  28. package/dist/api/app/bsky/actor/getPreferences.d.ts.map +1 -1
  29. package/dist/api/app/bsky/actor/getPreferences.js +29 -7
  30. package/dist/api/app/bsky/actor/getPreferences.js.map +1 -1
  31. package/dist/api/app/bsky/actor/getProfile.d.ts.map +1 -1
  32. package/dist/api/app/bsky/actor/getProfile.js +9 -1
  33. package/dist/api/app/bsky/actor/getProfile.js.map +1 -1
  34. package/dist/api/app/bsky/actor/getProfiles.d.ts.map +1 -1
  35. package/dist/api/app/bsky/actor/getProfiles.js +9 -1
  36. package/dist/api/app/bsky/actor/getProfiles.js.map +1 -1
  37. package/dist/api/app/bsky/actor/putPreferences.d.ts.map +1 -1
  38. package/dist/api/app/bsky/actor/putPreferences.js +30 -8
  39. package/dist/api/app/bsky/actor/putPreferences.js.map +1 -1
  40. package/dist/api/app/bsky/feed/getActorLikes.d.ts.map +1 -1
  41. package/dist/api/app/bsky/feed/getActorLikes.js +9 -1
  42. package/dist/api/app/bsky/feed/getActorLikes.js.map +1 -1
  43. package/dist/api/app/bsky/feed/getAuthorFeed.d.ts.map +1 -1
  44. package/dist/api/app/bsky/feed/getAuthorFeed.js +9 -1
  45. package/dist/api/app/bsky/feed/getAuthorFeed.js.map +1 -1
  46. package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
  47. package/dist/api/app/bsky/feed/getFeed.js +8 -1
  48. package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
  49. package/dist/api/app/bsky/feed/getPostThread.d.ts.map +1 -1
  50. package/dist/api/app/bsky/feed/getPostThread.js +8 -1
  51. package/dist/api/app/bsky/feed/getPostThread.js.map +1 -1
  52. package/dist/api/app/bsky/feed/getTimeline.d.ts.map +1 -1
  53. package/dist/api/app/bsky/feed/getTimeline.js +9 -1
  54. package/dist/api/app/bsky/feed/getTimeline.js.map +1 -1
  55. package/dist/api/app/bsky/notification/registerPush.d.ts.map +1 -1
  56. package/dist/api/app/bsky/notification/registerPush.js +16 -4
  57. package/dist/api/app/bsky/notification/registerPush.js.map +1 -1
  58. package/dist/api/com/atproto/identity/getRecommendedDidCredentials.d.ts.map +1 -1
  59. package/dist/api/com/atproto/identity/getRecommendedDidCredentials.js +5 -1
  60. package/dist/api/com/atproto/identity/getRecommendedDidCredentials.js.map +1 -1
  61. package/dist/api/com/atproto/identity/requestPlcOperationSignature.d.ts.map +1 -1
  62. package/dist/api/com/atproto/identity/requestPlcOperationSignature.js +9 -2
  63. package/dist/api/com/atproto/identity/requestPlcOperationSignature.js.map +1 -1
  64. package/dist/api/com/atproto/identity/signPlcOperation.d.ts.map +1 -1
  65. package/dist/api/com/atproto/identity/signPlcOperation.js +9 -1
  66. package/dist/api/com/atproto/identity/signPlcOperation.js.map +1 -1
  67. package/dist/api/com/atproto/identity/submitPlcOperation.d.ts.map +1 -1
  68. package/dist/api/com/atproto/identity/submitPlcOperation.js +5 -1
  69. package/dist/api/com/atproto/identity/submitPlcOperation.js.map +1 -1
  70. package/dist/api/com/atproto/identity/updateHandle.d.ts.map +1 -1
  71. package/dist/api/com/atproto/identity/updateHandle.js +6 -1
  72. package/dist/api/com/atproto/identity/updateHandle.js.map +1 -1
  73. package/dist/api/com/atproto/moderation/createReport.d.ts.map +1 -1
  74. package/dist/api/com/atproto/moderation/createReport.js +8 -3
  75. package/dist/api/com/atproto/moderation/createReport.js.map +1 -1
  76. package/dist/api/com/atproto/repo/applyWrites.d.ts.map +1 -1
  77. package/dist/api/com/atproto/repo/applyWrites.js +25 -19
  78. package/dist/api/com/atproto/repo/applyWrites.js.map +1 -1
  79. package/dist/api/com/atproto/repo/createRecord.d.ts.map +1 -1
  80. package/dist/api/com/atproto/repo/createRecord.js +10 -1
  81. package/dist/api/com/atproto/repo/createRecord.js.map +1 -1
  82. package/dist/api/com/atproto/repo/deleteRecord.d.ts.map +1 -1
  83. package/dist/api/com/atproto/repo/deleteRecord.js +12 -1
  84. package/dist/api/com/atproto/repo/deleteRecord.js.map +1 -1
  85. package/dist/api/com/atproto/repo/importRepo.d.ts.map +1 -1
  86. package/dist/api/com/atproto/repo/importRepo.js +7 -2
  87. package/dist/api/com/atproto/repo/importRepo.js.map +1 -1
  88. package/dist/api/com/atproto/repo/listMissingBlobs.d.ts.map +1 -1
  89. package/dist/api/com/atproto/repo/listMissingBlobs.js +6 -2
  90. package/dist/api/com/atproto/repo/listMissingBlobs.js.map +1 -1
  91. package/dist/api/com/atproto/repo/putRecord.d.ts.map +1 -1
  92. package/dist/api/com/atproto/repo/putRecord.js +17 -11
  93. package/dist/api/com/atproto/repo/putRecord.js.map +1 -1
  94. package/dist/api/com/atproto/repo/uploadBlob.d.ts.map +1 -1
  95. package/dist/api/com/atproto/repo/uploadBlob.js +5 -1
  96. package/dist/api/com/atproto/repo/uploadBlob.js.map +1 -1
  97. package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
  98. package/dist/api/com/atproto/server/activateAccount.js +7 -1
  99. package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
  100. package/dist/api/com/atproto/server/checkAccountStatus.d.ts.map +1 -1
  101. package/dist/api/com/atproto/server/checkAccountStatus.js +5 -1
  102. package/dist/api/com/atproto/server/checkAccountStatus.js.map +1 -1
  103. package/dist/api/com/atproto/server/confirmEmail.d.ts.map +1 -1
  104. package/dist/api/com/atproto/server/confirmEmail.js +6 -1
  105. package/dist/api/com/atproto/server/confirmEmail.js.map +1 -1
  106. package/dist/api/com/atproto/server/createAppPassword.d.ts.map +1 -1
  107. package/dist/api/com/atproto/server/createAppPassword.js +7 -1
  108. package/dist/api/com/atproto/server/createAppPassword.js.map +1 -1
  109. package/dist/api/com/atproto/server/deactivateAccount.d.ts.map +1 -1
  110. package/dist/api/com/atproto/server/deactivateAccount.js +9 -2
  111. package/dist/api/com/atproto/server/deactivateAccount.js.map +1 -1
  112. package/dist/api/com/atproto/server/deleteSession.d.ts.map +1 -1
  113. package/dist/api/com/atproto/server/deleteSession.js +3 -1
  114. package/dist/api/com/atproto/server/deleteSession.js.map +1 -1
  115. package/dist/api/com/atproto/server/getAccountInviteCodes.d.ts.map +1 -1
  116. package/dist/api/com/atproto/server/getAccountInviteCodes.js +8 -1
  117. package/dist/api/com/atproto/server/getAccountInviteCodes.js.map +1 -1
  118. package/dist/api/com/atproto/server/getServiceAuth.d.ts.map +1 -1
  119. package/dist/api/com/atproto/server/getServiceAuth.js +24 -13
  120. package/dist/api/com/atproto/server/getServiceAuth.js.map +1 -1
  121. package/dist/api/com/atproto/server/getSession.d.ts.map +1 -1
  122. package/dist/api/com/atproto/server/getSession.js +12 -19
  123. package/dist/api/com/atproto/server/getSession.js.map +1 -1
  124. package/dist/api/com/atproto/server/listAppPasswords.d.ts.map +1 -1
  125. package/dist/api/com/atproto/server/listAppPasswords.js +6 -1
  126. package/dist/api/com/atproto/server/listAppPasswords.js.map +1 -1
  127. package/dist/api/com/atproto/server/refreshSession.js +1 -1
  128. package/dist/api/com/atproto/server/refreshSession.js.map +1 -1
  129. package/dist/api/com/atproto/server/requestAccountDelete.d.ts.map +1 -1
  130. package/dist/api/com/atproto/server/requestAccountDelete.js +8 -1
  131. package/dist/api/com/atproto/server/requestAccountDelete.js.map +1 -1
  132. package/dist/api/com/atproto/server/requestEmailConfirmation.d.ts.map +1 -1
  133. package/dist/api/com/atproto/server/requestEmailConfirmation.js +6 -1
  134. package/dist/api/com/atproto/server/requestEmailConfirmation.js.map +1 -1
  135. package/dist/api/com/atproto/server/requestEmailUpdate.d.ts.map +1 -1
  136. package/dist/api/com/atproto/server/requestEmailUpdate.js +6 -1
  137. package/dist/api/com/atproto/server/requestEmailUpdate.js.map +1 -1
  138. package/dist/api/com/atproto/server/revokeAppPassword.d.ts.map +1 -1
  139. package/dist/api/com/atproto/server/revokeAppPassword.js +6 -1
  140. package/dist/api/com/atproto/server/revokeAppPassword.js.map +1 -1
  141. package/dist/api/com/atproto/server/updateEmail.d.ts.map +1 -1
  142. package/dist/api/com/atproto/server/updateEmail.js +8 -1
  143. package/dist/api/com/atproto/server/updateEmail.js.map +1 -1
  144. package/dist/api/com/atproto/sync/deprecated/getCheckout.d.ts.map +1 -1
  145. package/dist/api/com/atproto/sync/deprecated/getCheckout.js +7 -2
  146. package/dist/api/com/atproto/sync/deprecated/getCheckout.js.map +1 -1
  147. package/dist/api/com/atproto/sync/deprecated/getHead.d.ts.map +1 -1
  148. package/dist/api/com/atproto/sync/deprecated/getHead.js +7 -2
  149. package/dist/api/com/atproto/sync/deprecated/getHead.js.map +1 -1
  150. package/dist/api/com/atproto/sync/getBlob.d.ts.map +1 -1
  151. package/dist/api/com/atproto/sync/getBlob.js +7 -3
  152. package/dist/api/com/atproto/sync/getBlob.js.map +1 -1
  153. package/dist/api/com/atproto/sync/getBlocks.d.ts.map +1 -1
  154. package/dist/api/com/atproto/sync/getBlocks.js +7 -2
  155. package/dist/api/com/atproto/sync/getBlocks.js.map +1 -1
  156. package/dist/api/com/atproto/sync/getLatestCommit.d.ts.map +1 -1
  157. package/dist/api/com/atproto/sync/getLatestCommit.js +7 -2
  158. package/dist/api/com/atproto/sync/getLatestCommit.js.map +1 -1
  159. package/dist/api/com/atproto/sync/getRecord.d.ts.map +1 -1
  160. package/dist/api/com/atproto/sync/getRecord.js +7 -2
  161. package/dist/api/com/atproto/sync/getRecord.js.map +1 -1
  162. package/dist/api/com/atproto/sync/getRepo.d.ts.map +1 -1
  163. package/dist/api/com/atproto/sync/getRepo.js +7 -3
  164. package/dist/api/com/atproto/sync/getRepo.js.map +1 -1
  165. package/dist/api/com/atproto/sync/listBlobs.d.ts.map +1 -1
  166. package/dist/api/com/atproto/sync/listBlobs.js +7 -3
  167. package/dist/api/com/atproto/sync/listBlobs.js.map +1 -1
  168. package/dist/api/com/atproto/temp/checkSignupQueue.d.ts.map +1 -1
  169. package/dist/api/com/atproto/temp/checkSignupQueue.js +7 -3
  170. package/dist/api/com/atproto/temp/checkSignupQueue.js.map +1 -1
  171. package/dist/auth-output.d.ts +45 -0
  172. package/dist/auth-output.d.ts.map +1 -0
  173. package/dist/auth-output.js +3 -0
  174. package/dist/auth-output.js.map +1 -0
  175. package/dist/auth-scope.d.ts +16 -0
  176. package/dist/auth-scope.d.ts.map +1 -0
  177. package/dist/auth-scope.js +40 -0
  178. package/dist/auth-scope.js.map +1 -0
  179. package/dist/auth-verifier.d.ts +50 -115
  180. package/dist/auth-verifier.d.ts.map +1 -1
  181. package/dist/auth-verifier.js +275 -366
  182. package/dist/auth-verifier.js.map +1 -1
  183. package/dist/config/config.d.ts +2 -1
  184. package/dist/config/config.d.ts.map +1 -1
  185. package/dist/config/config.js +2 -1
  186. package/dist/config/config.js.map +1 -1
  187. package/dist/config/env.d.ts +1 -0
  188. package/dist/config/env.d.ts.map +1 -1
  189. package/dist/config/env.js +3 -1
  190. package/dist/config/env.js.map +1 -1
  191. package/dist/context.d.ts.map +1 -1
  192. package/dist/context.js +5 -5
  193. package/dist/context.js.map +1 -1
  194. package/dist/lexicon/index.d.ts +230 -230
  195. package/dist/lexicon/index.d.ts.map +1 -1
  196. package/dist/lexicon/index.js +687 -687
  197. package/dist/lexicon/index.js.map +1 -1
  198. package/dist/lexicon/lexicons.d.ts +16650 -16650
  199. package/dist/lexicon/lexicons.js +9267 -9267
  200. package/dist/lexicon/lexicons.js.map +1 -1
  201. package/dist/pipethrough.d.ts +5 -3
  202. package/dist/pipethrough.d.ts.map +1 -1
  203. package/dist/pipethrough.js +42 -15
  204. package/dist/pipethrough.js.map +1 -1
  205. package/dist/sequencer/events.d.ts +13 -13
  206. package/dist/util/http.d.ts +7 -0
  207. package/dist/util/http.d.ts.map +1 -0
  208. package/dist/util/http.js +31 -0
  209. package/dist/util/http.js.map +1 -0
  210. package/dist/util/types.d.ts +5 -0
  211. package/dist/util/types.d.ts.map +1 -0
  212. package/dist/util/types.js +3 -0
  213. package/dist/util/types.js.map +1 -0
  214. package/package.json +4 -3
  215. package/src/account-manager/account-manager.ts +1 -1
  216. package/src/account-manager/helpers/auth.ts +1 -1
  217. package/src/account-manager/helpers/authorization-request.ts +8 -4
  218. package/src/actor-store/preference/reader.ts +3 -4
  219. package/src/actor-store/preference/transactor.ts +6 -7
  220. package/src/actor-store/preference/util.ts +15 -5
  221. package/src/api/app/bsky/actor/getPreferences.ts +33 -8
  222. package/src/api/app/bsky/actor/getProfile.ts +9 -1
  223. package/src/api/app/bsky/actor/getProfiles.ts +9 -1
  224. package/src/api/app/bsky/actor/putPreferences.ts +35 -12
  225. package/src/api/app/bsky/feed/getActorLikes.ts +9 -1
  226. package/src/api/app/bsky/feed/getAuthorFeed.ts +9 -1
  227. package/src/api/app/bsky/feed/getFeed.ts +9 -2
  228. package/src/api/app/bsky/feed/getPostThread.ts +8 -1
  229. package/src/api/app/bsky/feed/getTimeline.ts +9 -1
  230. package/src/api/app/bsky/notification/registerPush.ts +16 -5
  231. package/src/api/com/atproto/identity/getRecommendedDidCredentials.ts +5 -1
  232. package/src/api/com/atproto/identity/requestPlcOperationSignature.ts +9 -2
  233. package/src/api/com/atproto/identity/signPlcOperation.ts +9 -1
  234. package/src/api/com/atproto/identity/submitPlcOperation.ts +5 -1
  235. package/src/api/com/atproto/identity/updateHandle.ts +6 -1
  236. package/src/api/com/atproto/moderation/createReport.ts +8 -3
  237. package/src/api/com/atproto/repo/applyWrites.ts +28 -20
  238. package/src/api/com/atproto/repo/createRecord.ts +12 -1
  239. package/src/api/com/atproto/repo/deleteRecord.ts +14 -1
  240. package/src/api/com/atproto/repo/importRepo.ts +9 -2
  241. package/src/api/com/atproto/repo/listMissingBlobs.ts +7 -2
  242. package/src/api/com/atproto/repo/putRecord.ts +18 -10
  243. package/src/api/com/atproto/repo/uploadBlob.ts +6 -2
  244. package/src/api/com/atproto/server/activateAccount.ts +10 -2
  245. package/src/api/com/atproto/server/checkAccountStatus.ts +5 -1
  246. package/src/api/com/atproto/server/confirmEmail.ts +6 -1
  247. package/src/api/com/atproto/server/createAppPassword.ts +9 -1
  248. package/src/api/com/atproto/server/deactivateAccount.ts +11 -2
  249. package/src/api/com/atproto/server/deleteSession.ts +3 -1
  250. package/src/api/com/atproto/server/getAccountInviteCodes.ts +11 -2
  251. package/src/api/com/atproto/server/getServiceAuth.ts +37 -18
  252. package/src/api/com/atproto/server/getSession.ts +20 -27
  253. package/src/api/com/atproto/server/listAppPasswords.ts +8 -1
  254. package/src/api/com/atproto/server/refreshSession.ts +1 -1
  255. package/src/api/com/atproto/server/requestAccountDelete.ts +11 -2
  256. package/src/api/com/atproto/server/requestEmailConfirmation.ts +6 -1
  257. package/src/api/com/atproto/server/requestEmailUpdate.ts +6 -1
  258. package/src/api/com/atproto/server/revokeAppPassword.ts +8 -1
  259. package/src/api/com/atproto/server/updateEmail.ts +11 -2
  260. package/src/api/com/atproto/sync/deprecated/getCheckout.ts +7 -6
  261. package/src/api/com/atproto/sync/deprecated/getHead.ts +7 -6
  262. package/src/api/com/atproto/sync/getBlob.ts +7 -7
  263. package/src/api/com/atproto/sync/getBlocks.ts +7 -6
  264. package/src/api/com/atproto/sync/getLatestCommit.ts +7 -6
  265. package/src/api/com/atproto/sync/getRecord.ts +7 -6
  266. package/src/api/com/atproto/sync/getRepo.ts +7 -7
  267. package/src/api/com/atproto/sync/listBlobs.ts +7 -7
  268. package/src/api/com/atproto/temp/checkSignupQueue.ts +8 -2
  269. package/src/auth-output.ts +51 -0
  270. package/src/auth-scope.ts +40 -0
  271. package/src/auth-verifier.ts +404 -520
  272. package/src/config/config.ts +7 -7
  273. package/src/config/env.ts +5 -1
  274. package/src/context.ts +6 -5
  275. package/src/lexicon/index.ts +1235 -1235
  276. package/src/lexicon/lexicons.ts +9416 -9416
  277. package/src/pipethrough.ts +61 -18
  278. package/src/util/http.ts +31 -0
  279. package/src/util/types.ts +7 -0
  280. package/tests/oauth.test.ts +11 -37
  281. package/tests/preferences.test.ts +7 -3
  282. package/tsconfig.build.tsbuildinfo +1 -1
@@ -36,32 +36,20 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.createPublicKeyObject = exports.createSecretKeyObject = exports.parseBasicAuth = exports.parseAuthorizationHeader = exports.AuthVerifier = exports.RoleStatus = exports.AuthScope = void 0;
39
+ exports.createPublicKeyObject = exports.createSecretKeyObject = exports.AuthVerifier = void 0;
40
+ exports.isUserOrAdmin = isUserOrAdmin;
40
41
  const node_crypto_1 = require("node:crypto");
41
42
  const jose = __importStar(require("jose"));
42
43
  const key_encoder_1 = __importDefault(require("key-encoder"));
43
44
  const common_1 = require("@atproto/common");
44
45
  const identity_1 = require("@atproto/identity");
45
46
  const oauth_provider_1 = require("@atproto/oauth-provider");
47
+ const oauth_scopes_1 = require("@atproto/oauth-scopes");
46
48
  const xrpc_server_1 = require("@atproto/xrpc-server");
49
+ const auth_scope_1 = require("./auth-scope");
47
50
  const db_1 = require("./db");
48
51
  const logger_1 = require("./logger");
49
- // @TODO sync-up with current method names, consider backwards compat.
50
- var AuthScope;
51
- (function (AuthScope) {
52
- AuthScope["Access"] = "com.atproto.access";
53
- AuthScope["Refresh"] = "com.atproto.refresh";
54
- AuthScope["AppPass"] = "com.atproto.appPass";
55
- AuthScope["AppPassPrivileged"] = "com.atproto.appPassPrivileged";
56
- AuthScope["SignupQueued"] = "com.atproto.signupQueued";
57
- AuthScope["Takendown"] = "com.atproto.takendown";
58
- })(AuthScope || (exports.AuthScope = AuthScope = {}));
59
- var RoleStatus;
60
- (function (RoleStatus) {
61
- RoleStatus[RoleStatus["Valid"] = 0] = "Valid";
62
- RoleStatus[RoleStatus["Invalid"] = 1] = "Invalid";
63
- RoleStatus[RoleStatus["Missing"] = 2] = "Missing";
64
- })(RoleStatus || (exports.RoleStatus = RoleStatus = {}));
52
+ const http_1 = require("./util/http");
65
53
  class AuthVerifier {
66
54
  constructor(accountManager, idResolver, oauthVerifier, opts) {
67
55
  Object.defineProperty(this, "accountManager", {
@@ -107,70 +95,21 @@ class AuthVerifier {
107
95
  value: void 0
108
96
  });
109
97
  // verifiers (arrow fns to preserve scope)
110
- Object.defineProperty(this, "accessStandard", {
98
+ Object.defineProperty(this, "unauthenticated", {
111
99
  enumerable: true,
112
100
  configurable: true,
113
101
  writable: true,
114
- value: (opts = {}) => async (ctx) => {
115
- return this.validateAccessToken(ctx, [
116
- AuthScope.Access,
117
- AuthScope.AppPassPrivileged,
118
- AuthScope.AppPass,
119
- ...(opts.additional ?? []),
120
- ], opts);
121
- }
122
- });
123
- Object.defineProperty(this, "accessFull", {
124
- enumerable: true,
125
- configurable: true,
126
- writable: true,
127
- value: (opts = {}) => (ctx) => {
128
- return this.validateAccessToken(ctx, [AuthScope.Access, ...(opts.additional ?? [])], opts);
129
- }
130
- });
131
- Object.defineProperty(this, "accessPrivileged", {
132
- enumerable: true,
133
- configurable: true,
134
- writable: true,
135
- value: (opts = {}) => (ctx) => {
136
- return this.validateAccessToken(ctx, [
137
- AuthScope.Access,
138
- AuthScope.AppPassPrivileged,
139
- ...(opts.additional ?? []),
140
- ]);
141
- }
142
- });
143
- Object.defineProperty(this, "refresh", {
144
- enumerable: true,
145
- configurable: true,
146
- writable: true,
147
- value: async (ctx) => {
148
- const { did, scope, tokenId } = await this.validateRefreshToken(ctx);
149
- return {
150
- credentials: {
151
- type: 'refresh',
152
- did,
153
- scope,
154
- tokenId,
155
- },
156
- };
157
- }
158
- });
159
- Object.defineProperty(this, "refreshExpired", {
160
- enumerable: true,
161
- configurable: true,
162
- writable: true,
163
- value: async (ctx) => {
164
- const { did, scope, tokenId } = await this.validateRefreshToken(ctx, {
165
- clockTolerance: Infinity,
166
- });
102
+ value: (ctx) => {
103
+ setAuthHeaders(ctx.res);
104
+ // @NOTE this auth method is typically used as fallback when no other auth
105
+ // method is applicable. This means that the presence of an "authorization"
106
+ // header means that that header is invalid (as it did not match any of the
107
+ // other auth methods).
108
+ if (ctx.req.headers['authorization']) {
109
+ throw new xrpc_server_1.AuthRequiredError('Invalid authorization header');
110
+ }
167
111
  return {
168
- credentials: {
169
- type: 'refresh',
170
- did,
171
- scope,
172
- tokenId,
173
- },
112
+ credentials: null,
174
113
  };
175
114
  }
176
115
  });
@@ -179,111 +118,78 @@ class AuthVerifier {
179
118
  configurable: true,
180
119
  writable: true,
181
120
  value: async (ctx) => {
182
- this.setAuthHeaders(ctx);
183
- return this.validateAdminToken(ctx);
184
- }
185
- });
186
- Object.defineProperty(this, "optionalAccessOrAdminToken", {
187
- enumerable: true,
188
- configurable: true,
189
- writable: true,
190
- value: (opts = {}) => async (ctx) => {
191
- if (isAccessToken(ctx.req)) {
192
- return await this.accessStandard(opts)(ctx);
121
+ setAuthHeaders(ctx.res);
122
+ const parsed = parseBasicAuth(ctx.req);
123
+ if (!parsed) {
124
+ throw new xrpc_server_1.AuthRequiredError();
193
125
  }
194
- else if (isBasicToken(ctx.req)) {
195
- return await this.adminToken(ctx);
196
- }
197
- else {
198
- return this.null(ctx);
126
+ const { username, password } = parsed;
127
+ if (username !== 'admin' || password !== this._adminPass) {
128
+ throw new xrpc_server_1.AuthRequiredError();
199
129
  }
130
+ return { credentials: { type: 'admin_token' } };
200
131
  }
201
132
  });
202
- Object.defineProperty(this, "userServiceAuth", {
133
+ Object.defineProperty(this, "modService", {
203
134
  enumerable: true,
204
135
  configurable: true,
205
136
  writable: true,
206
137
  value: async (ctx) => {
207
- const payload = await this.verifyServiceJwt(ctx, {
208
- aud: null,
209
- iss: null,
210
- });
211
- if (payload.aud !== this.dids.pds &&
212
- (!this.dids.entryway || payload.aud !== this.dids.entryway)) {
213
- throw new xrpc_server_1.AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
138
+ setAuthHeaders(ctx.res);
139
+ if (!this.dids.modService) {
140
+ throw new xrpc_server_1.AuthRequiredError('Untrusted issuer', 'UntrustedIss');
214
141
  }
142
+ const payload = await this.verifyServiceJwt(ctx.req, {
143
+ iss: [this.dids.modService, `${this.dids.modService}#atproto_labeler`],
144
+ });
215
145
  return {
216
146
  credentials: {
217
- type: 'user_service_auth',
218
- aud: payload.aud,
147
+ type: 'mod_service',
219
148
  did: payload.iss,
220
149
  },
221
150
  };
222
151
  }
223
152
  });
224
- Object.defineProperty(this, "userServiceAuthOptional", {
153
+ Object.defineProperty(this, "moderator", {
225
154
  enumerable: true,
226
155
  configurable: true,
227
156
  writable: true,
228
157
  value: async (ctx) => {
229
- if (isBearerToken(ctx.req)) {
230
- return await this.userServiceAuth(ctx);
158
+ const type = extractAuthType(ctx.req);
159
+ if (type === AuthType.BEARER) {
160
+ return this.modService(ctx);
231
161
  }
232
162
  else {
233
- return this.null(ctx);
234
- }
235
- }
236
- });
237
- Object.defineProperty(this, "accessOrUserServiceAuth", {
238
- enumerable: true,
239
- configurable: true,
240
- writable: true,
241
- value: (opts = {}) => async (ctx) => {
242
- const token = bearerTokenFromReq(ctx.req);
243
- if (token) {
244
- const payload = jose.decodeJwt(token);
245
- if (payload['lxm']) {
246
- return this.userServiceAuth(ctx);
247
- }
163
+ return this.adminToken(ctx);
248
164
  }
249
- return this.accessStandard(opts)(ctx);
250
165
  }
251
166
  });
252
- Object.defineProperty(this, "modService", {
167
+ Object.defineProperty(this, "userServiceAuth", {
253
168
  enumerable: true,
254
169
  configurable: true,
255
170
  writable: true,
256
171
  value: async (ctx) => {
257
- if (!this.dids.modService) {
258
- throw new xrpc_server_1.AuthRequiredError('Untrusted issuer', 'UntrustedIss');
259
- }
260
- const payload = await this.verifyServiceJwt(ctx, {
261
- aud: null,
262
- iss: [this.dids.modService, `${this.dids.modService}#atproto_labeler`],
263
- });
264
- if (payload.aud !== this.dids.pds &&
265
- (!this.dids.entryway || payload.aud !== this.dids.entryway)) {
266
- throw new xrpc_server_1.AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
267
- }
172
+ setAuthHeaders(ctx.res);
173
+ const payload = await this.verifyServiceJwt(ctx.req);
268
174
  return {
269
175
  credentials: {
270
- type: 'mod_service',
271
- aud: payload.aud,
272
- iss: payload.iss,
176
+ type: 'user_service_auth',
177
+ did: payload.iss,
273
178
  },
274
179
  };
275
180
  }
276
181
  });
277
- Object.defineProperty(this, "moderator", {
182
+ Object.defineProperty(this, "userServiceAuthOptional", {
278
183
  enumerable: true,
279
184
  configurable: true,
280
185
  writable: true,
281
186
  value: async (ctx) => {
282
- if (isBearerToken(ctx.req)) {
283
- return this.modService(ctx);
187
+ const type = extractAuthType(ctx.req);
188
+ if (type === AuthType.BEARER) {
189
+ return await this.userServiceAuth(ctx);
284
190
  }
285
191
  else {
286
- return this.adminToken(ctx);
192
+ return this.unauthenticated(ctx);
287
193
  }
288
194
  }
289
195
  });
@@ -292,132 +198,131 @@ class AuthVerifier {
292
198
  this._adminPass = opts.adminPass;
293
199
  this.dids = opts.dids;
294
200
  }
295
- async validateAdminToken({ req, }) {
296
- const parsed = (0, exports.parseBasicAuth)(req.headers.authorization);
297
- if (!parsed) {
298
- throw new xrpc_server_1.AuthRequiredError();
299
- }
300
- const { username, password } = parsed;
301
- if (username !== 'admin' || password !== this._adminPass) {
302
- throw new xrpc_server_1.AuthRequiredError();
303
- }
304
- return { credentials: { type: 'admin_token' } };
201
+ access(options) {
202
+ const { scopes, ...statusOptions } = options;
203
+ const verifyJwtOptions = {
204
+ audience: this.dids.pds,
205
+ typ: 'at+jwt',
206
+ scopes:
207
+ // @NOTE We can reject taken down credentials based on the scope if
208
+ // "checkTakedown" is set.
209
+ statusOptions.checkTakedown && scopes.includes(auth_scope_1.AuthScope.Takendown)
210
+ ? scopes.filter((s) => s !== auth_scope_1.AuthScope.Takendown)
211
+ : scopes,
212
+ };
213
+ return async (ctx) => {
214
+ setAuthHeaders(ctx.res);
215
+ const { sub: did, scope } = await this.verifyBearerJwt(ctx.req, verifyJwtOptions);
216
+ await this.verifyStatus(did, statusOptions);
217
+ return {
218
+ credentials: { type: 'access', did, scope },
219
+ };
220
+ };
305
221
  }
306
- async validateRefreshToken(ctx, verifyOptions) {
307
- const result = await this.validateBearerToken(ctx, [AuthScope.Refresh], {
308
- ...verifyOptions,
222
+ refresh(options) {
223
+ const verifyOptions = {
224
+ clockTolerance: options?.allowExpired ? Infinity : undefined,
309
225
  typ: 'refresh+jwt',
310
226
  // when using entryway, proxying refresh credentials
311
227
  audience: this.dids.entryway ? this.dids.entryway : this.dids.pds,
312
- });
313
- const tokenId = result.payload.jti;
314
- if (!tokenId) {
315
- throw new xrpc_server_1.AuthRequiredError('Unexpected missing refresh token id', 'MissingTokenId');
316
- }
317
- return { ...result, tokenId };
228
+ scopes: [auth_scope_1.AuthScope.Refresh],
229
+ };
230
+ return async (ctx) => {
231
+ setAuthHeaders(ctx.res);
232
+ const result = await this.verifyBearerJwt(ctx.req, verifyOptions);
233
+ const tokenId = result.jti;
234
+ if (!tokenId) {
235
+ throw new xrpc_server_1.AuthRequiredError('Unexpected missing refresh token id', 'MissingTokenId');
236
+ }
237
+ return {
238
+ credentials: {
239
+ type: 'refresh',
240
+ did: result.sub,
241
+ scope: result.scope,
242
+ tokenId,
243
+ },
244
+ };
245
+ };
318
246
  }
319
- async validateBearerToken(ctx, scopes, verifyOptions) {
320
- this.setAuthHeaders(ctx);
321
- const token = bearerTokenFromReq(ctx.req);
322
- if (!token) {
323
- throw new xrpc_server_1.AuthRequiredError(undefined, 'AuthMissing');
324
- }
325
- const { payload, protectedHeader } = await this.jwtVerify(token,
326
- // @TODO: Once all access & refresh tokens have a "typ" claim (i.e. 90
327
- // days after this code was deployed), replace the following line with
328
- // "verifyOptions," (to re-enable the verification of the "typ" property
329
- // from verifyJwt()). Once the change is made, the "if" block below that
330
- // checks for "typ" can be removed.
331
- {
332
- ...verifyOptions,
333
- typ: undefined,
247
+ authorization({ scopes = auth_scope_1.ACCESS_STANDARD, additional = [], ...options }) {
248
+ const access = this.access({
249
+ ...options,
250
+ scopes: [...scopes, ...additional],
334
251
  });
335
- // @TODO: remove the next check once all access & refresh tokens have "typ"
336
- // Note: when removing the check, make sure that the "verifyOptions"
337
- // contains the "typ" property, so that the token is verified correctly by
338
- // this.verifyJwt()
339
- if (protectedHeader.typ && verifyOptions.typ !== protectedHeader.typ) {
340
- // Temporarily allow historical tokens without "typ" to pass through. See:
341
- // createAccessToken() and createRefreshToken() in
342
- // src/account-manager/helpers/auth.ts
343
- throw new xrpc_server_1.InvalidRequestError('Invalid token type', 'InvalidToken');
344
- }
345
- const { sub, aud, scope } = payload;
346
- if (typeof sub !== 'string' || !sub.startsWith('did:')) {
347
- throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
348
- }
349
- if (aud !== undefined &&
350
- (typeof aud !== 'string' || !aud.startsWith('did:'))) {
351
- throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
352
- }
353
- if (payload['cnf'] !== undefined) {
354
- // Proof-of-Possession (PoP) tokens are not allowed here
355
- // https://www.rfc-editor.org/rfc/rfc7800.html
356
- throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
357
- }
358
- if (!isAuthScope(scope) || (scopes.length > 0 && !scopes.includes(scope))) {
359
- throw new xrpc_server_1.InvalidRequestError('Bad token scope', 'InvalidToken');
360
- }
361
- return {
362
- did: sub,
363
- scope,
364
- audience: aud,
365
- token,
366
- payload,
252
+ const oauth = this.oauth(options);
253
+ return async (ctx) => {
254
+ const type = extractAuthType(ctx.req);
255
+ if (type === AuthType.BEARER) {
256
+ return access(ctx);
257
+ }
258
+ if (type === AuthType.DPOP) {
259
+ return oauth(ctx);
260
+ }
261
+ // Auth headers are set through the access and oauth methods so we only
262
+ // need to set them here if we reach this point
263
+ setAuthHeaders(ctx.res);
264
+ if (type !== null) {
265
+ throw new xrpc_server_1.InvalidRequestError('Unexpected authorization type', 'InvalidToken');
266
+ }
267
+ throw new xrpc_server_1.AuthRequiredError(undefined, 'AuthMissing');
367
268
  };
368
269
  }
369
- async validateAccessToken(ctx, scopes, { checkTakedown = false, checkDeactivated = false, } = {}) {
370
- this.setAuthHeaders(ctx);
371
- let accessOutput;
372
- const [type] = (0, exports.parseAuthorizationHeader)(ctx.req.headers.authorization);
373
- switch (type) {
374
- case AuthType.BEARER: {
375
- accessOutput = await this.validateBearerAccessToken(ctx, scopes);
376
- break;
270
+ authorizationOrAdminTokenOptional(opts) {
271
+ const authorization = this.authorization(opts);
272
+ return async (ctx) => {
273
+ const type = extractAuthType(ctx.req);
274
+ if (type === AuthType.BEARER || type === AuthType.DPOP) {
275
+ return authorization(ctx);
377
276
  }
378
- case AuthType.DPOP: {
379
- accessOutput = await this.validateDpopAccessToken(ctx, scopes);
380
- break;
277
+ else if (type === AuthType.BASIC) {
278
+ return this.adminToken(ctx);
381
279
  }
382
- case null:
383
- throw new xrpc_server_1.AuthRequiredError(undefined, 'AuthMissing');
384
- default:
385
- throw new xrpc_server_1.InvalidRequestError('Unexpected authorization type', 'InvalidToken');
386
- }
387
- if (checkTakedown || checkDeactivated) {
388
- const found = await this.accountManager.getAccount(accessOutput.credentials.did, {
389
- includeDeactivated: true,
390
- includeTakenDown: true,
391
- });
392
- if (!found) {
393
- // will be turned into ExpiredToken for the client if proxied by entryway
394
- throw new xrpc_server_1.ForbiddenError('Account not found', 'AccountNotFound');
280
+ else {
281
+ return this.unauthenticated(ctx);
395
282
  }
396
- if (checkTakedown && (0, db_1.softDeleted)(found)) {
397
- throw new xrpc_server_1.AuthRequiredError('Account has been taken down', 'AccountTakedown');
283
+ };
284
+ }
285
+ authorizationOrUserServiceAuth(options) {
286
+ const authorizationVerifier = this.authorization(options);
287
+ return async (ctx) => {
288
+ if (isDefinitelyServiceAuth(ctx.req)) {
289
+ return this.userServiceAuth(ctx);
398
290
  }
399
- if (checkDeactivated && found.deactivatedAt) {
400
- throw new xrpc_server_1.AuthRequiredError('Account is deactivated', 'AccountDeactivated');
291
+ else {
292
+ return authorizationVerifier(ctx);
401
293
  }
402
- }
403
- return accessOutput;
294
+ };
404
295
  }
405
- async validateDpopAccessToken(ctx, scopes) {
406
- this.setAuthHeaders(ctx);
407
- const { req } = ctx;
408
- const res = 'res' in ctx ? ctx.res : null;
409
- // https://datatracker.ietf.org/doc/html/rfc9449#section-8.2
410
- if (res) {
296
+ oauth({ authorize, ...verifyStatusOptions }) {
297
+ const verifyTokenOptions = {
298
+ audience: [this.dids.pds],
299
+ scope: ['atproto'],
300
+ };
301
+ return async (ctx) => {
302
+ setAuthHeaders(ctx.res);
303
+ const { req, res } = ctx;
304
+ // https://datatracker.ietf.org/doc/html/rfc9449#section-8.2
411
305
  const dpopNonce = this.oauthVerifier.nextDpopNonce();
412
306
  if (dpopNonce) {
413
307
  res.setHeader('DPoP-Nonce', dpopNonce);
414
308
  res.appendHeader('Access-Control-Expose-Headers', 'DPoP-Nonce');
415
309
  }
416
- }
417
- try {
418
- const originalUrl = ('originalUrl' in req && req.originalUrl) || req.url || '/';
310
+ const originalUrl = req.originalUrl || req.url || '/';
419
311
  const url = new URL(originalUrl, this._publicUrl);
420
- const { tokenClaims, dpopProof } = await this.oauthVerifier.authenticateRequest(req.method || 'GET', url, req.headers, { audience: [this.dids.pds] });
312
+ const { tokenClaims, dpopProof } = await this.oauthVerifier
313
+ .authenticateRequest(req.method || 'GET', url, req.headers, verifyTokenOptions)
314
+ .catch((err) => {
315
+ // Make sure to include any WWW-Authenticate header in the response
316
+ // (particularly useful for DPoP's "use_dpop_nonce" error)
317
+ if (err instanceof oauth_provider_1.WWWAuthenticateError) {
318
+ res.setHeader('WWW-Authenticate', err.wwwAuthenticateHeader);
319
+ res.appendHeader('Access-Control-Expose-Headers', 'WWW-Authenticate');
320
+ }
321
+ if (err instanceof oauth_provider_1.OAuthError) {
322
+ throw new xrpc_server_1.XRPCError(err.status, err.error_description, err.error);
323
+ }
324
+ throw err;
325
+ });
421
326
  // @TODO drop this once oauth provider no longer accepts DPoP proof with
422
327
  // query or fragment in "htu" claim.
423
328
  if (dpopProof?.htu.match(/[?#]/)) {
@@ -426,68 +331,103 @@ class AuthVerifier {
426
331
  htu: dpopProof.htu,
427
332
  }, 'DPoP proof "htu" contains query or fragment');
428
333
  }
429
- const { sub } = tokenClaims;
430
- if (typeof sub !== 'string' || !sub.startsWith('did:')) {
334
+ const { sub: did } = tokenClaims;
335
+ if (typeof did !== 'string' || !did.startsWith('did:')) {
431
336
  throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
432
337
  }
433
- const oauthScopes = new Set(tokenClaims.scope?.split(' '));
434
- if (!oauthScopes.has('transition:generic')) {
435
- throw new xrpc_server_1.AuthRequiredError('Missing required scope: transition:generic', 'InvalidToken');
436
- }
437
- const scopeEquivalent = oauthScopes.has('transition:chat.bsky')
438
- ? AuthScope.AppPassPrivileged
439
- : AuthScope.AppPass;
440
- if (!scopes.includes(scopeEquivalent)) {
441
- // AppPassPrivileged is sufficient but was not provided "transition:chat.bsky"
442
- if (scopes.includes(AuthScope.AppPassPrivileged)) {
443
- throw new xrpc_server_1.InvalidRequestError('Missing required scope: transition:chat.bsky', 'InvalidToken');
444
- }
445
- // AuthScope.Access and AuthScope.SignupQueued do not have an OAuth
446
- // scope equivalent.
447
- throw new xrpc_server_1.InvalidRequestError('DPoP access token cannot be used for this request', 'InvalidToken');
338
+ await this.verifyStatus(did, verifyStatusOptions);
339
+ const permissions = new oauth_scopes_1.PermissionSetTransition(tokenClaims.scope?.split(' '));
340
+ // Should never happen
341
+ if (!permissions.scopes.has('atproto')) {
342
+ throw new xrpc_server_1.InvalidRequestError('OAuth token does not have "atproto" scope', 'InvalidToken');
448
343
  }
344
+ await authorize(permissions, ctx);
449
345
  return {
450
346
  credentials: {
451
347
  type: 'oauth',
452
- did: tokenClaims.sub,
453
- scope: scopeEquivalent,
454
- oauthScopes,
455
- isPrivileged: scopeEquivalent === AuthScope.AppPassPrivileged,
348
+ did,
349
+ permissions,
456
350
  },
457
351
  };
458
- }
459
- catch (err) {
460
- // Make sure to include any WWW-Authenticate header in the response
461
- // (particularly useful for DPoP's "use_dpop_nonce" error)
462
- if (res && err instanceof oauth_provider_1.WWWAuthenticateError) {
463
- res.setHeader('WWW-Authenticate', err.wwwAuthenticateHeader);
464
- res.appendHeader('Access-Control-Expose-Headers', 'WWW-Authenticate');
352
+ };
353
+ }
354
+ async verifyStatus(did, { checkTakedown = false, checkDeactivated = false }) {
355
+ if (checkTakedown || checkDeactivated) {
356
+ const found = await this.accountManager.getAccount(did, {
357
+ includeDeactivated: true,
358
+ includeTakenDown: true,
359
+ });
360
+ if (!found) {
361
+ // will be turned into ExpiredToken for the client if proxied by entryway
362
+ throw new xrpc_server_1.ForbiddenError('Account not found', 'AccountNotFound');
363
+ }
364
+ if (checkTakedown && (0, db_1.softDeleted)(found)) {
365
+ throw new xrpc_server_1.AuthRequiredError('Account has been taken down', 'AccountTakedown');
465
366
  }
466
- if (err instanceof oauth_provider_1.OAuthError) {
467
- throw new xrpc_server_1.XRPCError(err.status, err.error_description, err.error);
367
+ if (checkDeactivated && found.deactivatedAt) {
368
+ throw new xrpc_server_1.AuthRequiredError('Account is deactivated', 'AccountDeactivated');
468
369
  }
469
- throw err;
470
370
  }
471
371
  }
472
- async validateBearerAccessToken(ctx, scopes) {
473
- const { did, scope } = await this.validateBearerToken(ctx, scopes, {
474
- audience: this.dids.pds,
475
- typ: 'at+jwt',
372
+ /**
373
+ * Wraps {@link jose.jwtVerify} into a function that also validates the token
374
+ * payload's type and wraps errors into {@link InvalidRequestError}.
375
+ */
376
+ async verifyBearerJwt(req, { scopes, ...options }) {
377
+ const token = bearerTokenFromReq(req);
378
+ if (!token) {
379
+ throw new xrpc_server_1.AuthRequiredError(undefined, 'AuthMissing');
380
+ }
381
+ const { payload, protectedHeader } = await jose
382
+ .jwtVerify(token, this._jwtKey, { ...options, typ: undefined })
383
+ .catch((cause) => {
384
+ if (cause instanceof jose.errors.JWTExpired) {
385
+ throw new xrpc_server_1.InvalidRequestError('Token has expired', 'ExpiredToken', {
386
+ cause,
387
+ });
388
+ }
389
+ else {
390
+ throw new xrpc_server_1.InvalidRequestError('Token could not be verified', 'InvalidToken', { cause });
391
+ }
476
392
  });
477
- const isPrivileged = scope === AuthScope.Access || scope === AuthScope.AppPassPrivileged;
478
- return {
479
- credentials: {
480
- type: 'access',
481
- did,
482
- scope,
483
- isPrivileged,
484
- },
485
- };
393
+ // @NOTE: the "typ" is now set in production environments, so we should be
394
+ // able to safely check it through jose.jwtVerify(). However, tests depend
395
+ // on @atproto/pds-entryway which does not set "typ" in the access tokens.
396
+ // For that reason, we still allow it to be missing.
397
+ if (protectedHeader.typ && options.typ !== protectedHeader.typ) {
398
+ throw new xrpc_server_1.InvalidRequestError('Invalid token type', 'InvalidToken');
399
+ }
400
+ const { sub, aud, scope, lxm, cnf, jti } = payload;
401
+ if (typeof lxm !== 'undefined') {
402
+ // Service auth tokens should never make it to here. But since service
403
+ // auth tokens do not have a "typ" header, the "typ" check above will not
404
+ // catch them. This check here is mainly to protect against the
405
+ // hypothetical case in which a PDS would issue service auth tokens using
406
+ // its private key.
407
+ throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
408
+ }
409
+ if (typeof cnf !== 'undefined') {
410
+ // Proof-of-Possession (PoP) tokens are not allowed here
411
+ // https://www.rfc-editor.org/rfc/rfc7800.html
412
+ throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
413
+ }
414
+ if (typeof sub !== 'string' || !sub.startsWith('did:')) {
415
+ throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
416
+ }
417
+ if (typeof aud !== 'string' || !aud.startsWith('did:')) {
418
+ throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
419
+ }
420
+ if (typeof jti !== 'string' && typeof jti !== 'undefined') {
421
+ throw new xrpc_server_1.InvalidRequestError('Malformed token', 'InvalidToken');
422
+ }
423
+ if (!(0, auth_scope_1.isAuthScope)(scope) || !scopes.includes(scope)) {
424
+ throw new xrpc_server_1.InvalidRequestError('Bad token scope', 'InvalidToken');
425
+ }
426
+ return { sub, aud, jti, scope: scope };
486
427
  }
487
- async verifyServiceJwt(ctx, opts) {
488
- this.setAuthHeaders(ctx);
428
+ async verifyServiceJwt(req, opts) {
489
429
  const getSigningKey = async (iss, forceRefresh) => {
490
- if (opts.iss !== null && !opts.iss.includes(iss)) {
430
+ if (opts?.iss && !opts.iss.includes(iss)) {
491
431
  throw new xrpc_server_1.AuthRequiredError('Untrusted issuer', 'UntrustedIss');
492
432
  }
493
433
  const [did, serviceId] = iss.split('#');
@@ -506,60 +446,41 @@ class AuthVerifier {
506
446
  }
507
447
  return didKey;
508
448
  };
509
- const jwtStr = bearerTokenFromReq(ctx.req);
449
+ const jwtStr = bearerTokenFromReq(req);
510
450
  if (!jwtStr) {
511
451
  throw new xrpc_server_1.AuthRequiredError('missing jwt', 'MissingJwt');
512
452
  }
513
- const nsid = (0, xrpc_server_1.parseReqNsid)(ctx.req);
514
- const payload = await (0, xrpc_server_1.verifyJwt)(jwtStr, opts.aud, nsid, getSigningKey);
515
- return { iss: payload.iss, aud: payload.aud };
516
- }
517
- null(ctx) {
518
- this.setAuthHeaders(ctx);
519
- return {
520
- credentials: null,
521
- };
522
- }
523
- isUserOrAdmin(auth, did) {
524
- if (!auth.credentials) {
525
- return false;
526
- }
527
- else if (auth.credentials.type === 'admin_token') {
528
- return true;
529
- }
530
- else {
531
- return auth.credentials.did === did;
532
- }
533
- }
534
- async jwtVerify(token, verifyOptions) {
535
- try {
536
- return await jose.jwtVerify(token, this._jwtKey, verifyOptions);
537
- }
538
- catch (err) {
539
- if (err?.['code'] === 'ERR_JWT_EXPIRED') {
540
- throw new xrpc_server_1.InvalidRequestError('Token has expired', 'ExpiredToken');
541
- }
542
- throw new xrpc_server_1.InvalidRequestError('Token could not be verified', 'InvalidToken');
543
- }
544
- }
545
- setAuthHeaders(ctx) {
546
- const res = 'res' in ctx ? ctx.res : null;
547
- if (res) {
548
- res.setHeader('Cache-Control', 'private');
549
- vary(res, 'Authorization');
453
+ const nsid = (0, xrpc_server_1.parseReqNsid)(req);
454
+ const payload = await (0, xrpc_server_1.verifyJwt)(jwtStr, null, nsid, getSigningKey);
455
+ if (payload.aud !== this.dids.pds &&
456
+ (!this.dids.entryway || payload.aud !== this.dids.entryway)) {
457
+ throw new xrpc_server_1.AuthRequiredError('jwt audience does not match service did', 'BadJwtAudience');
550
458
  }
459
+ return payload;
551
460
  }
552
461
  }
553
462
  exports.AuthVerifier = AuthVerifier;
554
463
  // HELPERS
555
464
  // ---------
465
+ function isUserOrAdmin(auth, did) {
466
+ if (!auth.credentials) {
467
+ return false;
468
+ }
469
+ else if (auth.credentials.type === 'admin_token') {
470
+ return true;
471
+ }
472
+ else {
473
+ return auth.credentials.did === did;
474
+ }
475
+ }
556
476
  var AuthType;
557
477
  (function (AuthType) {
558
478
  AuthType["BASIC"] = "Basic";
559
479
  AuthType["BEARER"] = "Bearer";
560
480
  AuthType["DPOP"] = "DPoP";
561
481
  })(AuthType || (AuthType = {}));
562
- const parseAuthorizationHeader = (authorization) => {
482
+ const parseAuthorizationHeader = (req) => {
483
+ const authorization = req.headers['authorization'];
563
484
  if (!authorization)
564
485
  return [null];
565
486
  const result = authorization.split(' ');
@@ -573,26 +494,29 @@ const parseAuthorizationHeader = (authorization) => {
573
494
  return [type, result[1]];
574
495
  throw new xrpc_server_1.InvalidRequestError(`Unsupported authorization type: ${result[0]}`, 'InvalidToken');
575
496
  };
576
- exports.parseAuthorizationHeader = parseAuthorizationHeader;
577
- const isAccessToken = (req) => {
578
- const [type] = (0, exports.parseAuthorizationHeader)(req.headers.authorization);
579
- return type === AuthType.BEARER || type === AuthType.DPOP;
580
- };
581
- const isBearerToken = (req) => {
582
- const [type] = (0, exports.parseAuthorizationHeader)(req.headers.authorization);
583
- return type === AuthType.BEARER;
497
+ /**
498
+ * @note Not all service auth tokens are guaranteed to have "lxm" claim, so this
499
+ * function should not be used to verify service auth tokens. It is only used to
500
+ * check if a token is definitely a service auth token.
501
+ */
502
+ const isDefinitelyServiceAuth = (req) => {
503
+ const token = bearerTokenFromReq(req);
504
+ if (!token)
505
+ return false;
506
+ const payload = jose.decodeJwt(token);
507
+ return payload['lxm'] != null;
584
508
  };
585
- const isBasicToken = (req) => {
586
- const [type] = (0, exports.parseAuthorizationHeader)(req.headers.authorization);
587
- return type === AuthType.BASIC;
509
+ const extractAuthType = (req) => {
510
+ const [type] = parseAuthorizationHeader(req);
511
+ return type;
588
512
  };
589
513
  const bearerTokenFromReq = (req) => {
590
- const [type, token] = (0, exports.parseAuthorizationHeader)(req.headers.authorization);
514
+ const [type, token] = parseAuthorizationHeader(req);
591
515
  return type === AuthType.BEARER ? token : null;
592
516
  };
593
- const parseBasicAuth = (authorizationHeader) => {
517
+ const parseBasicAuth = (req) => {
594
518
  try {
595
- const [type, b64] = (0, exports.parseAuthorizationHeader)(authorizationHeader);
519
+ const [type, b64] = parseAuthorizationHeader(req);
596
520
  if (type !== AuthType.BASIC)
597
521
  return null;
598
522
  const decoded = Buffer.from(b64, 'base64').toString('utf8');
@@ -608,33 +532,18 @@ const parseBasicAuth = (authorizationHeader) => {
608
532
  return null;
609
533
  }
610
534
  };
611
- exports.parseBasicAuth = parseBasicAuth;
612
- const authScopes = new Set(Object.values(AuthScope));
613
- const isAuthScope = (val) => {
614
- return authScopes.has(val);
615
- };
616
535
  const createSecretKeyObject = (secret) => {
617
536
  return (0, node_crypto_1.createSecretKey)(Buffer.from(secret));
618
537
  };
619
538
  exports.createSecretKeyObject = createSecretKeyObject;
539
+ const keyEncoder = new key_encoder_1.default('secp256k1');
620
540
  const createPublicKeyObject = (publicKeyHex) => {
621
541
  const key = keyEncoder.encodePublic(publicKeyHex, 'raw', 'pem');
622
542
  return (0, node_crypto_1.createPublicKey)({ format: 'pem', key });
623
543
  };
624
544
  exports.createPublicKeyObject = createPublicKeyObject;
625
- const keyEncoder = new key_encoder_1.default('secp256k1');
626
- function vary(res, value) {
627
- const current = res.getHeader('Vary');
628
- if (current == null || typeof current === 'number') {
629
- res.setHeader('Vary', value);
630
- }
631
- else {
632
- const alreadyIncluded = Array.isArray(current)
633
- ? current.some((value) => value.includes(value))
634
- : current.includes(value);
635
- if (!alreadyIncluded) {
636
- res.appendHeader('Vary', value);
637
- }
638
- }
545
+ function setAuthHeaders(res) {
546
+ res.setHeader('Cache-Control', 'private');
547
+ (0, http_1.appendVary)(res, 'Authorization');
639
548
  }
640
549
  //# sourceMappingURL=auth-verifier.js.map