@atproto/oauth-provider 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/client/client-manager.d.ts.map +1 -1
  3. package/dist/client/client-manager.js +0 -7
  4. package/dist/client/client-manager.js.map +1 -1
  5. package/dist/client/client.js +6 -6
  6. package/dist/client/client.js.map +1 -1
  7. package/dist/device/device-manager.js +1 -1
  8. package/dist/device/device-manager.js.map +1 -1
  9. package/dist/dpop/dpop-manager.js +15 -15
  10. package/dist/dpop/dpop-manager.js.map +1 -1
  11. package/dist/errors/access-denied-error.d.ts +4 -7
  12. package/dist/errors/access-denied-error.d.ts.map +1 -1
  13. package/dist/errors/access-denied-error.js +4 -13
  14. package/dist/errors/access-denied-error.js.map +1 -1
  15. package/dist/errors/account-selection-required-error.d.ts +2 -2
  16. package/dist/errors/account-selection-required-error.d.ts.map +1 -1
  17. package/dist/errors/account-selection-required-error.js +2 -2
  18. package/dist/errors/account-selection-required-error.js.map +1 -1
  19. package/dist/errors/authorization-error.d.ts +10 -0
  20. package/dist/errors/authorization-error.d.ts.map +1 -0
  21. package/dist/errors/authorization-error.js +31 -0
  22. package/dist/errors/authorization-error.js.map +1 -0
  23. package/dist/errors/consent-required-error.d.ts +2 -2
  24. package/dist/errors/consent-required-error.d.ts.map +1 -1
  25. package/dist/errors/consent-required-error.js +2 -2
  26. package/dist/errors/consent-required-error.js.map +1 -1
  27. package/dist/errors/error-parser.d.ts.map +1 -1
  28. package/dist/errors/error-parser.js +2 -1
  29. package/dist/errors/error-parser.js.map +1 -1
  30. package/dist/errors/invalid-authorization-details-error.d.ts +2 -2
  31. package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -1
  32. package/dist/errors/invalid-authorization-details-error.js +2 -2
  33. package/dist/errors/invalid-authorization-details-error.js.map +1 -1
  34. package/dist/errors/invalid-scope-error.d.ts +2 -2
  35. package/dist/errors/invalid-scope-error.d.ts.map +1 -1
  36. package/dist/errors/invalid-scope-error.js +2 -2
  37. package/dist/errors/invalid-scope-error.js.map +1 -1
  38. package/dist/errors/login-required-error.d.ts +2 -3
  39. package/dist/errors/login-required-error.d.ts.map +1 -1
  40. package/dist/errors/login-required-error.js +2 -7
  41. package/dist/errors/login-required-error.js.map +1 -1
  42. package/dist/lib/http/response.d.ts +4 -4
  43. package/dist/lib/http/response.d.ts.map +1 -1
  44. package/dist/lib/http/response.js +8 -7
  45. package/dist/lib/http/response.js.map +1 -1
  46. package/dist/lib/http/stream.d.ts +1 -0
  47. package/dist/lib/http/stream.d.ts.map +1 -1
  48. package/dist/lib/http/stream.js +6 -0
  49. package/dist/lib/http/stream.js.map +1 -1
  50. package/dist/lib/util/error.d.ts +2 -0
  51. package/dist/lib/util/error.d.ts.map +1 -0
  52. package/dist/lib/util/error.js +11 -0
  53. package/dist/lib/util/error.js.map +1 -0
  54. package/dist/lib/util/zod-error.d.ts +3 -1
  55. package/dist/lib/util/zod-error.d.ts.map +1 -1
  56. package/dist/lib/util/zod-error.js +20 -10
  57. package/dist/lib/util/zod-error.js.map +1 -1
  58. package/dist/metadata/build-metadata.d.ts +0 -1
  59. package/dist/metadata/build-metadata.d.ts.map +1 -1
  60. package/dist/metadata/build-metadata.js +6 -2
  61. package/dist/metadata/build-metadata.js.map +1 -1
  62. package/dist/oauth-errors.d.ts +1 -1
  63. package/dist/oauth-errors.d.ts.map +1 -1
  64. package/dist/oauth-errors.js +1 -1
  65. package/dist/oauth-errors.js.map +1 -1
  66. package/dist/oauth-hooks.d.ts +17 -3
  67. package/dist/oauth-hooks.d.ts.map +1 -1
  68. package/dist/oauth-hooks.js +7 -4
  69. package/dist/oauth-hooks.js.map +1 -1
  70. package/dist/oauth-provider.d.ts +1 -0
  71. package/dist/oauth-provider.d.ts.map +1 -1
  72. package/dist/oauth-provider.js +35 -49
  73. package/dist/oauth-provider.js.map +1 -1
  74. package/dist/oauth-verifier.d.ts +2 -1
  75. package/dist/oauth-verifier.d.ts.map +1 -1
  76. package/dist/oauth-verifier.js.map +1 -1
  77. package/dist/request/request-manager.d.ts +5 -5
  78. package/dist/request/request-manager.d.ts.map +1 -1
  79. package/dist/request/request-manager.js +63 -45
  80. package/dist/request/request-manager.js.map +1 -1
  81. package/dist/request/request-store.d.ts +6 -6
  82. package/dist/request/request-store.d.ts.map +1 -1
  83. package/dist/result/authorization-result-authorize-page.d.ts +2 -3
  84. package/dist/result/authorization-result-authorize-page.d.ts.map +1 -1
  85. package/dist/router/assets/send-authorization-page.js +3 -2
  86. package/dist/router/assets/send-authorization-page.js.map +1 -1
  87. package/dist/router/create-api-middleware.d.ts.map +1 -1
  88. package/dist/router/create-api-middleware.js +68 -48
  89. package/dist/router/create-api-middleware.js.map +1 -1
  90. package/dist/router/create-authorization-page-middleware.d.ts.map +1 -1
  91. package/dist/router/create-authorization-page-middleware.js +19 -17
  92. package/dist/router/create-authorization-page-middleware.js.map +1 -1
  93. package/dist/router/create-oauth-middleware.d.ts.map +1 -1
  94. package/dist/router/create-oauth-middleware.js +21 -18
  95. package/dist/router/create-oauth-middleware.js.map +1 -1
  96. package/dist/router/send-redirect.js +2 -2
  97. package/dist/router/send-redirect.js.map +1 -1
  98. package/dist/token/token-manager.js +1 -1
  99. package/dist/token/verify-token-claims.d.ts +1 -0
  100. package/dist/token/verify-token-claims.d.ts.map +1 -1
  101. package/dist/token/verify-token-claims.js.map +1 -1
  102. package/dist/types/authorization-response-error.d.ts +5 -0
  103. package/dist/types/authorization-response-error.d.ts.map +1 -0
  104. package/dist/types/authorization-response-error.js +21 -0
  105. package/dist/types/authorization-response-error.js.map +1 -0
  106. package/dist/types/par-response-error.d.ts +5 -0
  107. package/dist/types/par-response-error.d.ts.map +1 -0
  108. package/dist/types/par-response-error.js +22 -0
  109. package/dist/types/par-response-error.js.map +1 -0
  110. package/package.json +7 -6
  111. package/src/client/client-manager.ts +0 -8
  112. package/src/client/client.ts +6 -6
  113. package/src/device/device-manager.ts +1 -1
  114. package/src/dpop/dpop-manager.ts +16 -16
  115. package/src/errors/access-denied-error.ts +6 -33
  116. package/src/errors/account-selection-required-error.ts +2 -2
  117. package/src/errors/authorization-error.ts +45 -0
  118. package/src/errors/consent-required-error.ts +2 -2
  119. package/src/errors/error-parser.ts +2 -1
  120. package/src/errors/invalid-authorization-details-error.ts +2 -2
  121. package/src/errors/invalid-scope-error.ts +2 -2
  122. package/src/errors/login-required-error.ts +2 -12
  123. package/src/lib/http/response.ts +14 -13
  124. package/src/lib/http/stream.ts +6 -0
  125. package/src/lib/util/error.ts +7 -0
  126. package/src/lib/util/zod-error.ts +23 -11
  127. package/src/metadata/build-metadata.ts +8 -3
  128. package/src/oauth-errors.ts +1 -1
  129. package/src/oauth-hooks.ts +18 -2
  130. package/src/oauth-provider.ts +37 -58
  131. package/src/oauth-verifier.ts +3 -1
  132. package/src/request/request-manager.ts +76 -55
  133. package/src/request/request-store.ts +6 -6
  134. package/src/result/authorization-result-authorize-page.ts +2 -3
  135. package/src/router/assets/send-authorization-page.ts +3 -3
  136. package/src/router/create-api-middleware.ts +92 -64
  137. package/src/router/create-authorization-page-middleware.ts +19 -21
  138. package/src/router/create-oauth-middleware.ts +28 -27
  139. package/src/router/send-redirect.ts +2 -2
  140. package/src/token/token-manager.ts +1 -1
  141. package/src/token/verify-token-claims.ts +8 -0
  142. package/src/types/authorization-response-error.ts +27 -0
  143. package/src/types/par-response-error.ts +25 -0
  144. package/tsconfig.build.tsbuildinfo +1 -1
  145. package/dist/errors/invalid-parameters-error.d.ts +0 -6
  146. package/dist/errors/invalid-parameters-error.d.ts.map +0 -1
  147. package/dist/errors/invalid-parameters-error.js +0 -11
  148. package/dist/errors/invalid-parameters-error.js.map +0 -1
  149. package/dist/request/request-info.d.ts +0 -14
  150. package/dist/request/request-info.d.ts.map +0 -1
  151. package/dist/request/request-info.js +0 -3
  152. package/dist/request/request-info.js.map +0 -1
  153. package/src/errors/invalid-parameters-error.ts +0 -12
  154. package/src/request/request-info.ts +0 -14
@@ -1 +1 @@
1
- {"version":3,"file":"send-redirect.js","sourceRoot":"","sources":["../../src/router/send-redirect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"send-redirect.js","sourceRoot":"","sources":["../../src/router/send-redirect.ts"],"names":[],"mappings":"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"}
@@ -188,7 +188,7 @@ class TokenManager {
188
188
  // @TODO Add another store method that atomically consumes the refresh token
189
189
  // with a lock.
190
190
  const tokenInfo = await this.findByRefreshToken(token).catch((err) => {
191
- throw invalid_token_error_js_1.InvalidTokenError.from(err, `Invalid refresh token`);
191
+ throw invalid_grant_error_js_1.InvalidGrantError.from(err, `Invalid refresh token`);
192
192
  });
193
193
  if (!tokenInfo) {
194
194
  throw new invalid_grant_error_js_1.InvalidGrantError(`Invalid refresh token`);
@@ -2,6 +2,7 @@ import { OAuthAccessToken, OAuthTokenType } from '@atproto/oauth-types';
2
2
  import { DpopProof } from '../oauth-verifier.js';
3
3
  import { SignedTokenPayload } from '../signer/signed-token-payload.js';
4
4
  import { TokenId } from './token-id.js';
5
+ export type { DpopProof, OAuthAccessToken, OAuthTokenType, SignedTokenPayload, TokenId, };
5
6
  export type VerifyTokenClaimsOptions = {
6
7
  /** One of these audience must be included in the token audience(s) */
7
8
  audience?: [string, ...string[]];
@@ -1 +1 @@
1
- {"version":3,"file":"verify-token-claims.d.ts","sourceRoot":"","sources":["../../src/token/verify-token-claims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAKvE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAKvC,MAAM,MAAM,wBAAwB,GAAG;IACrC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAChC,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,cAAc,CAAA;IACzB,WAAW,EAAE,kBAAkB,CAAA;IAC/B,SAAS,EAAE,IAAI,GAAG,SAAS,CAAA;CAC5B,CAAA;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,IAAI,GAAG,SAAS,EAC3B,OAAO,CAAC,EAAE,wBAAwB,GACjC,uBAAuB,CA0DzB"}
1
+ {"version":3,"file":"verify-token-claims.d.ts","sourceRoot":"","sources":["../../src/token/verify-token-claims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAKvE,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAA;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAKvC,YAAY,EACV,SAAS,EACT,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,OAAO,GACR,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAChC,gEAAgE;IAChE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,gBAAgB,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,cAAc,CAAA;IACzB,WAAW,EAAE,kBAAkB,CAAA;IAC/B,SAAS,EAAE,IAAI,GAAG,SAAS,CAAA;CAC5B,CAAA;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,OAAO,EAChB,SAAS,EAAE,cAAc,EACzB,WAAW,EAAE,kBAAkB,EAC/B,SAAS,EAAE,IAAI,GAAG,SAAS,EAC3B,OAAO,CAAC,EAAE,wBAAwB,GACjC,uBAAuB,CA0DzB"}
@@ -1 +1 @@
1
- {"version":3,"file":"verify-token-claims.js","sourceRoot":"","sources":["../../src/token/verify-token-claims.ts"],"names":[],"mappings":";;AA2BA,8CAiEC;AA3FD,mGAAwF;AACxF,uFAA6E;AAC7E,iDAA6C;AAC7C,wDAAsD;AAKtD,MAAM,MAAM,GAAG,QAAiC,CAAA;AAChD,MAAM,IAAI,GAAG,MAA+B,CAAA;AAiB5C,SAAgB,iBAAiB,CAC/B,KAAuB,EACvB,OAAgB,EAChB,SAAyB,EACzB,WAA+B,EAC/B,SAA2B,EAC3B,OAAkC;IAElC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAEhC,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,4DAA4D;QAC5D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,mCAAiB,CACzB,IAAI,EACJ,4DAA4D,SAAS,EAAE,CACxE,CAAA;QACH,CAAC;QAED,iDAAiD;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,mDAAqB,CAAC,qBAAqB,CAAC,CAAA;QACxD,CAAC;QAED,sEAAsE;QACtE,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC;YAC1C,MAAM,IAAI,8DAA0B,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,iEAAiE;QACjE,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,mCAAiB,CACzB,MAAM,EACN,qDAAqD,CACtD,CAAA;QACH,CAAC;QAED,oDAAoD;QACpD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,mCAAiB,CACzB,MAAM,EACN,+CAA+C,CAChD,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,IAAA,iBAAO,EAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,GAAG,IAAI,IAAI,IAAI,WAAW,CAAC,GAAG,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC;QACvE,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;IACzD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAA;AAC9D,CAAC"}
1
+ {"version":3,"file":"verify-token-claims.js","sourceRoot":"","sources":["../../src/token/verify-token-claims.ts"],"names":[],"mappings":";;AAmCA,8CAiEC;AAnGD,mGAAwF;AACxF,uFAA6E;AAC7E,iDAA6C;AAC7C,wDAAsD;AAKtD,MAAM,MAAM,GAAG,QAAiC,CAAA;AAChD,MAAM,IAAI,GAAG,MAA+B,CAAA;AAyB5C,SAAgB,iBAAiB,CAC/B,KAAuB,EACvB,OAAgB,EAChB,SAAyB,EACzB,WAA+B,EAC/B,SAA2B,EAC3B,OAAkC;IAElC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAEhC,IAAI,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;QACzB,4DAA4D;QAC5D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,mCAAiB,CACzB,IAAI,EACJ,4DAA4D,SAAS,EAAE,CACxE,CAAA;QACH,CAAC;QAED,iDAAiD;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,mDAAqB,CAAC,qBAAqB,CAAC,CAAA;QACxD,CAAC;QAED,sEAAsE;QACtE,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC;YAC1C,MAAM,IAAI,8DAA0B,EAAE,CAAA;QACxC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,iEAAiE;QACjE,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,mCAAiB,CACzB,MAAM,EACN,qDAAqD,CACtD,CAAA;QACH,CAAC;QAED,oDAAoD;QACpD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,mCAAiB,CACzB,MAAM,EACN,+CAA+C,CAChD,CAAA;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,IAAA,iBAAO,EAAC,WAAW,CAAC,GAAG,CAAC,CAAA;QACpC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAA;QAC5D,CAAC;IACH,CAAC;IAED,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;QAC5C,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;QACzD,CAAC;IACH,CAAC;IAED,IAAI,WAAW,CAAC,GAAG,IAAI,IAAI,IAAI,WAAW,CAAC,GAAG,GAAG,IAAI,IAAI,aAAa,EAAE,CAAC;QACvE,MAAM,IAAI,mCAAiB,CAAC,SAAS,EAAE,eAAe,CAAC,CAAA;IACzD,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,CAAA;AAC9D,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare const authorizationResponseErrorSchema: z.ZodUnion<[z.ZodEnum<["invalid_request", "unauthorized_client", "access_denied", "unsupported_response_type", "invalid_scope", "server_error", "temporarily_unavailable"]>, z.ZodEnum<["interaction_required", "login_required", "account_selection_required", "consent_required", "invalid_request_uri", "invalid_request_object", "request_not_supported", "request_uri_not_supported", "registration_not_supported"]>, z.ZodLiteral<"invalid_authorization_details">]>;
3
+ export type AuthorizationResponseError = z.infer<typeof authorizationResponseErrorSchema>;
4
+ export declare function isAuthorizationResponseError<T>(value: T): value is T & AuthorizationResponseError;
5
+ //# sourceMappingURL=authorization-response-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization-response-error.d.ts","sourceRoot":"","sources":["../../src/types/authorization-response-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,gCAAgC,4cAU3C,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAC9C,OAAO,gCAAgC,CACxC,CAAA;AAED,wBAAgB,4BAA4B,CAAC,CAAC,EAC5C,KAAK,EAAE,CAAC,GACP,KAAK,IAAI,CAAC,GAAG,0BAA0B,CAEzC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.authorizationResponseErrorSchema = void 0;
4
+ exports.isAuthorizationResponseError = isAuthorizationResponseError;
5
+ const zod_1 = require("zod");
6
+ const oauth_types_1 = require("@atproto/oauth-types");
7
+ exports.authorizationResponseErrorSchema = zod_1.z.union([
8
+ oauth_types_1.oauthAuthorizationResponseErrorSchema,
9
+ // OIDC authentication error response are not part of the ATproto flavoured
10
+ // OAuth but we allow them because they provide better feedback to the client
11
+ // (in particular when SSO is used).
12
+ oauth_types_1.oidcAuthorizationResponseErrorSchema,
13
+ // This error is defined by rfc9396 (not part of the OAuth 2.1 or OIDC). But
14
+ // since, in ATproto flavoured OAuth, client registration is a dynamic part of
15
+ // the authorization process, we allow it.
16
+ zod_1.z.literal('invalid_authorization_details'),
17
+ ]);
18
+ function isAuthorizationResponseError(value) {
19
+ return exports.authorizationResponseErrorSchema.safeParse(value).success;
20
+ }
21
+ //# sourceMappingURL=authorization-response-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorization-response-error.js","sourceRoot":"","sources":["../../src/types/authorization-response-error.ts"],"names":[],"mappings":";;;AAsBA,oEAIC;AA1BD,6BAAuB;AACvB,sDAG6B;AAEhB,QAAA,gCAAgC,GAAG,OAAC,CAAC,KAAK,CAAC;IACtD,mDAAqC;IACrC,2EAA2E;IAC3E,6EAA6E;IAC7E,oCAAoC;IACpC,kDAAoC;IACpC,4EAA4E;IAC5E,8EAA8E;IAC9E,0CAA0C;IAC1C,OAAC,CAAC,OAAO,CAAC,+BAA+B,CAAC;CAC3C,CAAC,CAAA;AAMF,SAAgB,4BAA4B,CAC1C,KAAQ;IAER,OAAO,wCAAgC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAA;AAClE,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { z } from 'zod';
2
+ export declare const parResponseErrorSchema: z.ZodIntersection<z.ZodUnion<[z.ZodEnum<["invalid_request", "unauthorized_client", "access_denied", "unsupported_response_type", "invalid_scope", "server_error", "temporarily_unavailable"]>, z.ZodEnum<["interaction_required", "login_required", "account_selection_required", "consent_required", "invalid_request_uri", "invalid_request_object", "request_not_supported", "request_uri_not_supported", "registration_not_supported"]>, z.ZodLiteral<"invalid_authorization_details">]>, z.ZodEnum<["invalid_request", "unauthorized_client", "unsupported_response_type", "invalid_scope", "server_error", "temporarily_unavailable"]>>;
3
+ export type PARResponseError = z.infer<typeof parResponseErrorSchema>;
4
+ export declare function isPARResponseError<T>(value: T): value is T & PARResponseError;
5
+ //# sourceMappingURL=par-response-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"par-response-error.d.ts","sourceRoot":"","sources":["../../src/types/par-response-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAQvB,eAAO,MAAM,sBAAsB,+mBAUlC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,gBAAgB,CAE7E"}
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parResponseErrorSchema = void 0;
4
+ exports.isPARResponseError = isPARResponseError;
5
+ const zod_1 = require("zod");
6
+ const authorization_response_error_js_1 = require("./authorization-response-error.js");
7
+ // https://datatracker.ietf.org/doc/html/rfc9126#section-2.3-1
8
+ // > Since initial processing of the pushed authorization request does not
9
+ // > involve resource owner interaction, error codes related to user
10
+ // > interaction, such as "access_denied", are never returned.
11
+ exports.parResponseErrorSchema = zod_1.z.intersection(authorization_response_error_js_1.authorizationResponseErrorSchema, zod_1.z.enum([
12
+ 'invalid_request',
13
+ 'unauthorized_client',
14
+ 'unsupported_response_type',
15
+ 'invalid_scope',
16
+ 'server_error',
17
+ 'temporarily_unavailable',
18
+ ]));
19
+ function isPARResponseError(value) {
20
+ return exports.parResponseErrorSchema.safeParse(value).success;
21
+ }
22
+ //# sourceMappingURL=par-response-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"par-response-error.js","sourceRoot":"","sources":["../../src/types/par-response-error.ts"],"names":[],"mappings":";;;AAsBA,gDAEC;AAxBD,6BAAuB;AACvB,uFAAoF;AAEpF,8DAA8D;AAC9D,0EAA0E;AAC1E,oEAAoE;AACpE,8DAA8D;AAEjD,QAAA,sBAAsB,GAAG,OAAC,CAAC,YAAY,CAClD,kEAAgC,EAChC,OAAC,CAAC,IAAI,CAAC;IACL,iBAAiB;IACjB,qBAAqB;IACrB,2BAA2B;IAC3B,eAAe;IACf,cAAc;IACd,yBAAyB;CAC1B,CAAC,CACH,CAAA;AAID,SAAgB,kBAAkB,CAAI,KAAQ;IAC5C,OAAO,8BAAsB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAA;AACxD,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/oauth-provider",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "license": "MIT",
5
5
  "description": "Generic OAuth2 and OpenID Connect provider for Node.js. Currently only supports features needed for Atproto.",
6
6
  "keywords": [
@@ -35,7 +35,7 @@
35
35
  "@hapi/address": "^5.1.1",
36
36
  "@hapi/bourne": "^3.0.0",
37
37
  "@hapi/content": "^6.0.0",
38
- "cookie": "^0.6.0",
38
+ "cookie": "^0.7.0",
39
39
  "disposable-email-domains-js": "^1.5.0",
40
40
  "forwarded": "^0.2.0",
41
41
  "http-errors": "^2.0.0",
@@ -51,10 +51,11 @@
51
51
  "@atproto/did": "0.1.5",
52
52
  "@atproto/jwk": "0.4.0",
53
53
  "@atproto/jwk-jose": "0.1.9",
54
- "@atproto/oauth-types": "0.3.1",
55
- "@atproto/oauth-provider-api": "0.1.5",
56
- "@atproto/oauth-provider-frontend": "0.1.9",
57
- "@atproto/oauth-provider-ui": "0.1.10",
54
+ "@atproto/oauth-types": "0.4.0",
55
+ "@atproto/oauth-provider-api": "0.2.0",
56
+ "@atproto/oauth-provider-frontend": "0.1.11",
57
+ "@atproto/oauth-provider-ui": "0.2.0",
58
+ "@atproto/oauth-scopes": "0.0.1",
58
59
  "@atproto/syntax": "0.4.0"
59
60
  },
60
61
  "devDependencies": {
@@ -259,14 +259,6 @@ export class ClientManager {
259
259
  throw new InvalidClientMetadataError(`Duplicate scope "${dupScope}"`)
260
260
  }
261
261
 
262
- for (const scope of scopes) {
263
- // Note, once we have dynamic scopes, this check will need to be
264
- // updated to check against the server's supported scopes.
265
- if (!this.serverMetadata.scopes_supported?.includes(scope)) {
266
- throw new InvalidClientMetadataError(`Unsupported scope "${scope}"`)
267
- }
268
- }
269
-
270
262
  const dupGrantType = metadata.grant_types.find(isDuplicate)
271
263
  if (dupGrantType) {
272
264
  throw new InvalidClientMetadataError(
@@ -24,10 +24,10 @@ import {
24
24
  OAuthRedirectUri,
25
25
  } from '@atproto/oauth-types'
26
26
  import { CLIENT_ASSERTION_MAX_AGE, JAR_MAX_AGE } from '../constants.js'
27
+ import { AuthorizationError } from '../errors/authorization-error.js'
27
28
  import { InvalidAuthorizationDetailsError } from '../errors/invalid-authorization-details-error.js'
28
29
  import { InvalidClientError } from '../errors/invalid-client-error.js'
29
30
  import { InvalidClientMetadataError } from '../errors/invalid-client-metadata-error.js'
30
- import { InvalidParametersError } from '../errors/invalid-parameters-error.js'
31
31
  import { InvalidRequestError } from '../errors/invalid-request-error.js'
32
32
  import { InvalidScopeError } from '../errors/invalid-scope-error.js'
33
33
  import { asArray } from '../lib/util/cast.js'
@@ -285,7 +285,7 @@ export class Client {
285
285
  parameters: Readonly<OAuthAuthorizationRequestParameters>,
286
286
  ): Readonly<OAuthAuthorizationRequestParameters> {
287
287
  if (parameters.client_id !== this.id) {
288
- throw new InvalidParametersError(
288
+ throw new AuthorizationError(
289
289
  parameters,
290
290
  'The "client_id" parameter field does not match the value used to authenticate the client',
291
291
  )
@@ -314,7 +314,7 @@ export class Client {
314
314
  }
315
315
 
316
316
  if (!this.metadata.response_types.includes(parameters.response_type)) {
317
- throw new InvalidParametersError(
317
+ throw new AuthorizationError(
318
318
  parameters,
319
319
  `Invalid response_type "${parameters.response_type}" requested by the client`,
320
320
  )
@@ -322,7 +322,7 @@ export class Client {
322
322
 
323
323
  if (parameters.response_type.includes('code')) {
324
324
  if (!this.metadata.grant_types.includes('authorization_code')) {
325
- throw new InvalidParametersError(
325
+ throw new AuthorizationError(
326
326
  parameters,
327
327
  `This client is not allowed to use the "authorization_code" grant type`,
328
328
  )
@@ -336,7 +336,7 @@ export class Client {
336
336
  compareRedirectUri(uri, redirect_uri),
337
337
  )
338
338
  ) {
339
- throw new InvalidParametersError(
339
+ throw new AuthorizationError(
340
340
  parameters,
341
341
  `Invalid redirect_uri ${redirect_uri}`,
342
342
  )
@@ -351,7 +351,7 @@ export class Client {
351
351
  // > "redirect_uri": OPTIONAL if only one redirect URI is registered for
352
352
  // > this client. REQUIRED if multiple redirect URIs are registered for this
353
353
  // > client.
354
- throw new InvalidParametersError(parameters, 'redirect_uri is required')
354
+ throw new AuthorizationError(parameters, 'redirect_uri is required')
355
355
  }
356
356
  }
357
357
 
@@ -261,7 +261,7 @@ export class DeviceManager {
261
261
  const rawValue = Object.hasOwn(cookies, name) ? cookies[name] : null
262
262
  if (!rawValue) return null
263
263
 
264
- const result = schema.safeParse(rawValue, { path: ['cookie', name] })
264
+ const result = schema.safeParse(rawValue)
265
265
  if (!result.success) return null
266
266
 
267
267
  const value = result.data
@@ -68,7 +68,7 @@ export class DpopManager {
68
68
  maxTokenAge: 10, // Will ensure presence & validity of "iat" claim
69
69
  clockTolerance: DPOP_NONCE_MAX_AGE / 1e3,
70
70
  }).catch((err) => {
71
- throw newInvalidDpopProofError('Failed to verify DPoP proof', err)
71
+ throw wrapInvalidDpopProofError(err, 'Failed to verify DPoP proof')
72
72
  })
73
73
 
74
74
  // @NOTE For legacy & backwards compatibility reason, we cannot use
@@ -86,20 +86,20 @@ export class DpopManager {
86
86
  const { ath, htm, htu, jti, nonce } = payload
87
87
 
88
88
  if (nonce !== undefined && typeof nonce !== 'string') {
89
- throw newInvalidDpopProofError('Invalid DPoP "nonce" type')
89
+ throw new InvalidDpopProofError('Invalid DPoP "nonce" type')
90
90
  }
91
91
 
92
92
  if (!jti || typeof jti !== 'string') {
93
- throw newInvalidDpopProofError('DPoP "jti" missing')
93
+ throw new InvalidDpopProofError('DPoP "jti" missing')
94
94
  }
95
95
 
96
96
  // Note rfc9110#section-9.1 states that the method name is case-sensitive
97
97
  if (!htm || htm !== httpMethod) {
98
- throw newInvalidDpopProofError('DPoP "htm" mismatch')
98
+ throw new InvalidDpopProofError('DPoP "htm" mismatch')
99
99
  }
100
100
 
101
101
  if (!htu || typeof htu !== 'string') {
102
- throw newInvalidDpopProofError('Invalid DPoP "htu" type')
102
+ throw new InvalidDpopProofError('Invalid DPoP "htu" type')
103
103
  }
104
104
 
105
105
  // > To reduce the likelihood of false negatives, servers SHOULD employ
@@ -109,7 +109,7 @@ export class DpopManager {
109
109
  //
110
110
  // RFC9449 section 4.3. Checking DPoP Proofs - https://datatracker.ietf.org/doc/html/rfc9449#section-4.3
111
111
  if (!htu || parseHtu(htu) !== normalizeHtuUrl(httpUrl)) {
112
- throw newInvalidDpopProofError('DPoP "htu" mismatch')
112
+ throw new InvalidDpopProofError('DPoP "htu" mismatch')
113
113
  }
114
114
 
115
115
  if (!nonce && this.dpopNonce) {
@@ -123,17 +123,17 @@ export class DpopManager {
123
123
  if (accessToken) {
124
124
  const accessTokenHash = createHash('sha256').update(accessToken).digest()
125
125
  if (ath !== accessTokenHash.toString('base64url')) {
126
- throw newInvalidDpopProofError('DPoP "ath" mismatch')
126
+ throw new InvalidDpopProofError('DPoP "ath" mismatch')
127
127
  }
128
128
  } else if (ath !== undefined) {
129
- throw newInvalidDpopProofError('DPoP "ath" claim not allowed')
129
+ throw new InvalidDpopProofError('DPoP "ath" claim not allowed')
130
130
  }
131
131
 
132
132
  // @NOTE we can assert there is a jwk because the jwtVerify used the
133
133
  // EmbeddedJWK key getter mechanism.
134
134
  const jwk = protectedHeader.jwk!
135
135
  const jkt = await calculateJwkThumbprint(jwk, 'sha256').catch((err) => {
136
- throw newInvalidDpopProofError('Failed to calculate jkt', err)
136
+ throw wrapInvalidDpopProofError(err, 'Failed to calculate jkt')
137
137
  })
138
138
 
139
139
  return { jti, jkt, htm, htu }
@@ -147,12 +147,12 @@ function extractProof(
147
147
  switch (typeof dpopHeader) {
148
148
  case 'string':
149
149
  if (dpopHeader) return dpopHeader
150
- throw newInvalidDpopProofError('DPoP header cannot be empty')
150
+ throw new InvalidDpopProofError('DPoP header cannot be empty')
151
151
  case 'object':
152
152
  // @NOTE the "0" case should never happen a node.js HTTP server will only
153
153
  // return an array if the header is set multiple times.
154
154
  if (dpopHeader.length === 1 && dpopHeader[0]) return dpopHeader[0]!
155
- throw newInvalidDpopProofError('DPoP header must contain a single proof')
155
+ throw new InvalidDpopProofError('DPoP header must contain a single proof')
156
156
  default:
157
157
  return null
158
158
  }
@@ -177,7 +177,7 @@ function normalizeHtuUrl(url: Readonly<URL>): string {
177
177
  function parseHtu(htu: string): string {
178
178
  const url = ifURL(htu)
179
179
  if (!url) {
180
- throw newInvalidDpopProofError('DPoP "htu" is not a valid URL')
180
+ throw new InvalidDpopProofError('DPoP "htu" is not a valid URL')
181
181
  }
182
182
 
183
183
  // @NOTE the checks bellow can be removed once once jwtPayloadSchema is used
@@ -185,11 +185,11 @@ function parseHtu(htu: string): string {
185
185
  // (though the htuSchema).
186
186
 
187
187
  if (url.password || url.username) {
188
- throw newInvalidDpopProofError('DPoP "htu" must not contain credentials')
188
+ throw new InvalidDpopProofError('DPoP "htu" must not contain credentials')
189
189
  }
190
190
 
191
191
  if (url.protocol !== 'http:' && url.protocol !== 'https:') {
192
- throw newInvalidDpopProofError('DPoP "htu" must be http or https')
192
+ throw new InvalidDpopProofError('DPoP "htu" must be http or https')
193
193
  }
194
194
 
195
195
  // @NOTE For legacy & backwards compatibility reason, we allow a query and
@@ -200,9 +200,9 @@ function parseHtu(htu: string): string {
200
200
  return normalizeHtuUrl(url)
201
201
  }
202
202
 
203
- function newInvalidDpopProofError(
203
+ function wrapInvalidDpopProofError(
204
+ err: unknown,
204
205
  title: string,
205
- err?: unknown,
206
206
  ): InvalidDpopProofError {
207
207
  const msg =
208
208
  err instanceof JOSEError || err instanceof ValidationError
@@ -1,39 +1,12 @@
1
- import {
2
- OAuthAuthenticationErrorResponse,
3
- OAuthAuthorizationRequestParameters,
4
- OidcAuthenticationErrorResponse,
5
- } from '@atproto/oauth-types'
6
- import { buildErrorPayload } from './error-parser.js'
7
- import { OAuthError } from './oauth-error.js'
1
+ import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
+ import { AuthorizationError } from './authorization-error.js'
8
3
 
9
- export type AuthenticationErrorResponse =
10
- | OAuthAuthenticationErrorResponse
11
- // OIDC authentication error response are not part of the ATproto flavoured
12
- // OAuth but we allow them because they provide better feedback to the client
13
- // (in particular when SSO is used).
14
- | OidcAuthenticationErrorResponse
15
- // This error is defined by rfc9396 (not part of the OAuth 2.1 or OIDC). But
16
- // since, in ATproto flavoured OAuth, client registration is a dynamic part of
17
- // the authorization process, we allow it.
18
- | 'invalid_authorization_details'
19
-
20
- export class AccessDeniedError extends OAuthError {
4
+ export class AccessDeniedError extends AuthorizationError {
21
5
  constructor(
22
- public readonly parameters: OAuthAuthorizationRequestParameters,
23
- error_description: string,
24
- error: AuthenticationErrorResponse = 'access_denied',
6
+ parameters: OAuthAuthorizationRequestParameters,
7
+ error_description = 'Access denied',
25
8
  cause?: unknown,
26
9
  ) {
27
- super(error, error_description, 400, cause)
28
- }
29
-
30
- static from(
31
- parameters: OAuthAuthorizationRequestParameters,
32
- cause: unknown,
33
- error: AuthenticationErrorResponse,
34
- ): AccessDeniedError {
35
- if (cause instanceof AccessDeniedError) return cause
36
- const { error_description } = buildErrorPayload(cause)
37
- return new AccessDeniedError(parameters, error_description, error, cause)
10
+ super(parameters, error_description, 'access_denied', cause)
38
11
  }
39
12
  }
@@ -1,7 +1,7 @@
1
1
  import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AccessDeniedError } from './access-denied-error.js'
2
+ import { AuthorizationError } from './authorization-error.js'
3
3
 
4
- export class AccountSelectionRequiredError extends AccessDeniedError {
4
+ export class AccountSelectionRequiredError extends AuthorizationError {
5
5
  constructor(
6
6
  parameters: OAuthAuthorizationRequestParameters,
7
7
  error_description = 'Account selection required',
@@ -0,0 +1,45 @@
1
+ import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
+ import {
3
+ AuthorizationResponseError,
4
+ isAuthorizationResponseError,
5
+ } from '../types/authorization-response-error.js'
6
+ import { buildErrorPayload } from './error-parser.js'
7
+ import { OAuthError } from './oauth-error.js'
8
+
9
+ export type { AuthorizationResponseError, OAuthAuthorizationRequestParameters }
10
+
11
+ export class AuthorizationError extends OAuthError {
12
+ constructor(
13
+ public readonly parameters: OAuthAuthorizationRequestParameters,
14
+ error_description: string,
15
+ error: AuthorizationResponseError = 'invalid_request',
16
+ cause?: unknown,
17
+ ) {
18
+ super(error, error_description, 400, cause)
19
+ }
20
+
21
+ static from(
22
+ parameters: OAuthAuthorizationRequestParameters,
23
+ cause: unknown,
24
+ ): AuthorizationError {
25
+ if (cause instanceof AuthorizationError) return cause
26
+ const payload = buildErrorPayload(cause)
27
+ return new AuthorizationError(
28
+ parameters,
29
+ payload.error_description,
30
+ isAuthorizationResponseError(payload.error)
31
+ ? payload.error // Propagate "error" derived from the cause
32
+ : rootCause(cause) instanceof OAuthError
33
+ ? 'invalid_request'
34
+ : 'server_error',
35
+ cause,
36
+ )
37
+ }
38
+ }
39
+
40
+ function rootCause(err: unknown): unknown {
41
+ while (err instanceof Error && err.cause != null) {
42
+ err = err.cause
43
+ }
44
+ return err
45
+ }
@@ -1,7 +1,7 @@
1
1
  import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AccessDeniedError } from './access-denied-error.js'
2
+ import { AuthorizationError } from './authorization-error.js'
3
3
 
4
- export class ConsentRequiredError extends AccessDeniedError {
4
+ export class ConsentRequiredError extends AuthorizationError {
5
5
  constructor(
6
6
  parameters: OAuthAuthorizationRequestParameters,
7
7
  error_description = 'User consent required',
@@ -1,6 +1,7 @@
1
1
  import { errors } from 'jose'
2
2
  import { ZodError } from 'zod'
3
3
  import { JwtVerifyError } from '@atproto/jwk'
4
+ import { formatZodError } from '../lib/util/zod-error.js'
4
5
  import { OAuthError } from './oauth-error.js'
5
6
 
6
7
  const { JOSEError } = errors
@@ -63,7 +64,7 @@ export function buildErrorPayload(error: unknown): ErrorPayload {
63
64
  if (error instanceof ZodError) {
64
65
  return {
65
66
  error: INVALID_REQUEST,
66
- error_description: error.issues[0]?.message || 'Invalid request',
67
+ error_description: formatZodError(error, 'Validation error'),
67
68
  }
68
69
  }
69
70
 
@@ -1,5 +1,5 @@
1
1
  import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AccessDeniedError } from './access-denied-error.js'
2
+ import { AuthorizationError } from './authorization-error.js'
3
3
 
4
4
  /**
5
5
  * @see
@@ -16,7 +16,7 @@ import { AccessDeniedError } from './access-denied-error.js'
16
16
  * - contains fields with invalid values for the authorization details type, or
17
17
  * - is missing required fields for the authorization details type.
18
18
  */
19
- export class InvalidAuthorizationDetailsError extends AccessDeniedError {
19
+ export class InvalidAuthorizationDetailsError extends AuthorizationError {
20
20
  constructor(
21
21
  parameters: OAuthAuthorizationRequestParameters,
22
22
  error_description: string,
@@ -1,10 +1,10 @@
1
1
  import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AccessDeniedError } from './access-denied-error.js'
2
+ import { AuthorizationError } from './authorization-error.js'
3
3
 
4
4
  /**
5
5
  * @see {@link https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-11#section-4.1.2.1}
6
6
  */
7
- export class InvalidScopeError extends AccessDeniedError {
7
+ export class InvalidScopeError extends AuthorizationError {
8
8
  constructor(
9
9
  parameters: OAuthAuthorizationRequestParameters,
10
10
  error_description: string,
@@ -1,7 +1,7 @@
1
1
  import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AccessDeniedError } from './access-denied-error.js'
2
+ import { AuthorizationError } from './authorization-error.js'
3
3
 
4
- export class LoginRequiredError extends AccessDeniedError {
4
+ export class LoginRequiredError extends AuthorizationError {
5
5
  constructor(
6
6
  parameters: OAuthAuthorizationRequestParameters,
7
7
  error_description = 'Login is required',
@@ -9,14 +9,4 @@ export class LoginRequiredError extends AccessDeniedError {
9
9
  ) {
10
10
  super(parameters, error_description, 'login_required', cause)
11
11
  }
12
-
13
- static from(
14
- parameters: OAuthAuthorizationRequestParameters,
15
- cause?: unknown,
16
- fallbackError?: string,
17
- ): LoginRequiredError {
18
- if (cause instanceof LoginRequiredError) return cause
19
-
20
- return new LoginRequiredError(parameters, fallbackError, cause)
21
- }
22
12
  }
@@ -101,16 +101,16 @@ export function cacheControlMiddleware(maxAge: number): Middleware<void> {
101
101
  }
102
102
  }
103
103
 
104
+ export type JsonResponse<P = unknown> = WriteResponseOptions & {
105
+ json: P
106
+ }
107
+
104
108
  export function jsonHandler<
105
109
  T,
106
110
  Req extends IncomingMessage = IncomingMessage,
107
111
  Res extends ServerResponse = ServerResponse,
108
112
  >(
109
- buildJson: (
110
- this: T,
111
- req: Req,
112
- res: Res,
113
- ) => Awaitable<{ payload: unknown; status?: number }>,
113
+ buildJson: (this: T, req: Req, res: Res) => Awaitable<JsonResponse>,
114
114
  ): Middleware<T, Req, Res> {
115
115
  return function (req, res, next) {
116
116
  // Ensure we can agree on a content encoding & type before starting to
@@ -120,14 +120,11 @@ export function jsonHandler<
120
120
  // promise and return it.
121
121
  void (async () => {
122
122
  try {
123
- const { payload, status = 200 } = await buildJson.call(this, req, res)
124
- writeJson(res, payload, { status })
125
- } catch (cause) {
126
- const error =
127
- cause instanceof Error
128
- ? cause
129
- : new Error('Failed to build JSON response', { cause })
130
- next(error satisfies Error)
123
+ const jsonResponse = await buildJson.call(this, req, res)
124
+ const { json, status = 200, ...options } = jsonResponse
125
+ writeJson(res, json, { ...options, status })
126
+ } catch (err) {
127
+ next(asError(err, 'Failed to build JSON response'))
131
128
  }
132
129
  })()
133
130
  } else {
@@ -135,3 +132,7 @@ export function jsonHandler<
135
132
  }
136
133
  }
137
134
  }
135
+
136
+ function asError(cause: unknown, message: string): Error {
137
+ return cause instanceof Error ? cause : new Error(message, { cause })
138
+ }
@@ -49,3 +49,9 @@ export async function parseHttpRequest<A extends readonly KnownNames[]>(
49
49
  Extract<KnownParser, { name: A[number] }>
50
50
  >
51
51
  }
52
+
53
+ export async function flushStream(stream: AsyncIterable<any>): Promise<void> {
54
+ for await (const _ of stream) {
55
+ // Consume the stream to completion
56
+ }
57
+ }
@@ -0,0 +1,7 @@
1
+ import { ZodError } from 'zod'
2
+ import { formatZodError } from './zod-error.js'
3
+
4
+ export function formatError(err: unknown, prefix: string): string {
5
+ if (err instanceof ZodError) return formatZodError(err, prefix)
6
+ return prefix
7
+ }