@remit/backend 0.0.82 → 0.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/backend",
3
- "version": "0.0.82",
3
+ "version": "0.0.83",
4
4
  "description": "Remit Mail Inspector API backend",
5
5
  "license": "MIT",
6
6
  "author": "",
@@ -72,6 +72,35 @@ test("no token and no bypass returns 401", async () => {
72
72
  assert.equal(result?.statusCode, 401);
73
73
  });
74
74
 
75
+ test("a tokenless GET to the Microsoft OAuth callback is admitted", async () => {
76
+ const event = buildEvent({
77
+ httpMethod: "GET",
78
+ path: "/accounts/oauth/microsoft/callback",
79
+ });
80
+
81
+ const result = await authenticateSelfHostRequest(event);
82
+
83
+ assert.equal(result, null);
84
+ assert.equal(event.requestContext.authorizer, undefined);
85
+ });
86
+
87
+ test("the callback exemption covers that path and method only", async () => {
88
+ const neighbour = buildEvent({
89
+ httpMethod: "GET",
90
+ path: "/accounts/oauth/microsoft/start",
91
+ });
92
+ const otherMethod = buildEvent({
93
+ httpMethod: "POST",
94
+ path: "/accounts/oauth/microsoft/callback",
95
+ });
96
+
97
+ assert.equal((await authenticateSelfHostRequest(neighbour))?.statusCode, 401);
98
+ assert.equal(
99
+ (await authenticateSelfHostRequest(otherMethod))?.statusCode,
100
+ 401,
101
+ );
102
+ });
103
+
75
104
  test("pre-injected claims (edge tier) short-circuit verification", async () => {
76
105
  _setVerifierForTest(async () => {
77
106
  throw new Error("verifier must not be called");
package/src/jwt-auth.ts CHANGED
@@ -55,6 +55,26 @@ const injectClaims = (
55
55
  const hasLocalBypass = (): boolean =>
56
56
  Boolean(process.env.LOCAL_ACCOUNT_CONFIG_ID);
57
57
 
58
+ /**
59
+ * The one route that runs without a token.
60
+ *
61
+ * Microsoft redirects the browser here after consent, so the request carries no
62
+ * Authorization header and no session to derive one from. The handler takes its
63
+ * identity from the HMAC-signed `state` parameter and validates it there; that
64
+ * signature is the gate, not a JWT.
65
+ *
66
+ * Hardcoded and single-entry, matching the edge exemption in
67
+ * packages/apisix/src/route-table.ts. `@useAuth(NoAuth)` in the spec does not
68
+ * open a path here — a future public route is added by hand.
69
+ */
70
+ const PUBLIC_ROUTE = {
71
+ method: "GET",
72
+ path: "/accounts/oauth/microsoft/callback",
73
+ };
74
+
75
+ const isPublicRoute = (event: APIGatewayProxyEvent): boolean =>
76
+ event.httpMethod === PUBLIC_ROUTE.method && event.path === PUBLIC_ROUTE.path;
77
+
58
78
  /**
59
79
  * Authenticate a self-host request from a better-auth RS256 JWT.
60
80
  *
@@ -71,6 +91,8 @@ const hasLocalBypass = (): boolean =>
71
91
  export const authenticateSelfHostRequest = async (
72
92
  event: APIGatewayProxyEvent,
73
93
  ): Promise<APIGatewayProxyResult | null> => {
94
+ if (isPublicRoute(event)) return null;
95
+
74
96
  const existingSub = event.requestContext?.authorizer?.claims?.sub;
75
97
  if (typeof existingSub === "string" && existingSub.length > 0) return null;
76
98