@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 +1 -1
- package/src/jwt-auth.test.ts +29 -0
- package/src/jwt-auth.ts +22 -0
package/package.json
CHANGED
package/src/jwt-auth.test.ts
CHANGED
|
@@ -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
|
|