Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/remove-option-casts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@seamless-auth/express": patch
---

Remove the redundant `as any` / option-object casts across the Express adapter so the compiler checks each option literal against its handler interface. These casts were the construct that previously let a mistyped option (`serviceAuthorization`) be silently dropped. No public API change. One internal cleanup with a visible edge case: the internal metrics handlers now reduce an array-valued query parameter to its first value rather than letting it reach the upstream comma-joined, which the scalar handler contract never supported.
7 changes: 3 additions & 4 deletions packages/express/src/createServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ export function createSeamlessAuthServer(
const resolvedPath = typeof path === "function" ? path(req) : path;
const upstream = await authFetch(
`${resolvedOpts.authServerUrl}/${resolvedPath}${queryString ? `?${queryString}` : ""}`,
options as any,
options,
);

const data = await upstream.json();
Expand Down Expand Up @@ -330,8 +330,7 @@ export function createSeamlessAuthServer(
audience: "seamless-auth",
keyId: resolvedOpts.jwksKid,
resolveClientIp: resolvedOpts.resolveClientIp,
forwardedClientIp: undefined,
} as any),
}),
);

r.post(
Expand Down Expand Up @@ -494,7 +493,7 @@ export function createSeamlessAuthServer(
method: "GET",
serviceAuthorization: buildProxyServiceAuthorization(resolvedOpts),
forwardedClientIp: buildForwardedClientIp(req, resolvedOpts.resolveClientIp),
} as any,
},
);

const data = await upstream.json();
Expand Down
26 changes: 13 additions & 13 deletions packages/express/src/handlers/admin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const getUsers = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const createUser = async (
Expand All @@ -57,7 +57,7 @@ export const createUser = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
body: req.body,
} as any),
}),
);

export const deleteUser = async (
Expand All @@ -73,7 +73,7 @@ export const deleteUser = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
body: req.body,
} as any),
}),
);

export const updateUser = async (
Expand All @@ -89,7 +89,7 @@ export const updateUser = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
body: req.body,
} as any),
}),
);

export const getUserDetail = async (
Expand All @@ -104,7 +104,7 @@ export const getUserDetail = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const getUserAnomalies = async (
Expand All @@ -119,7 +119,7 @@ export const getUserAnomalies = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const getAuthEvents = async (
Expand All @@ -135,7 +135,7 @@ export const getAuthEvents = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
query: req.query,
} as any),
}),
);

export const getCredentialCount = async (
Expand All @@ -150,7 +150,7 @@ export const getCredentialCount = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const listAllSessions = async (
Expand All @@ -166,7 +166,7 @@ export const listAllSessions = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
query: req.query,
} as any),
}),
);

export const listUserSessions = async (
Expand All @@ -181,7 +181,7 @@ export const listUserSessions = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const revokeUserSession = async (
Expand All @@ -196,7 +196,7 @@ export const revokeUserSession = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const revokeAllUserSessions = async (
Expand All @@ -211,7 +211,7 @@ export const revokeAllUserSessions = async (
authorization: buildServiceAuthorization(req, opts),
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any),
}),
);

export const recoverUserForDeviceReplacement = async (
Expand All @@ -227,5 +227,5 @@ export const recoverUserForDeviceReplacement = async (
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
body: req.body,
} as any),
}),
);
2 changes: 1 addition & 1 deletion packages/express/src/handlers/bootstrapAdmininvite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function bootstrapAdminInvite(
serviceAuthorization: opts.messaging
? buildInternalServiceAuthorization(opts)
: buildProxyServiceAuthorization(opts),
} as any);
});

if (result.error) {
return res.status(result.status).json({ error: result.error });
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/finishLogin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function finishLogin(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any,
},
{
authServerUrl: opts.authServerUrl,
audience: opts.audience,
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/finishRegister.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function finishRegister(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any,
},
{
authServerUrl: opts.authServerUrl,
audience: opts.audience,
Expand Down
35 changes: 26 additions & 9 deletions packages/express/src/handlers/internalMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,23 @@ function handle(res: Response, result: any) {
return res.status(result.status).json(result.body);
}

// Express types req.query as ParsedQs, whose values may be arrays or nested
// objects. The metrics handlers only forward scalar query params, so reduce to
// the first string value per key instead of casting the whole object.
function toQueryRecord(
query: Request["query"],
): Record<string, string | undefined> {
const record: Record<string, string | undefined> = {};
for (const [key, value] of Object.entries(query)) {
if (typeof value === "string") {
record[key] = value;
} else if (Array.isArray(value) && typeof value[0] === "string") {
record[key] = value[0];
}
}
return record;
}

export async function getAuthEventSummary(
req: Request,
res: Response,
Expand All @@ -34,8 +51,8 @@ export async function getAuthEventSummary(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
query: req.query as any,
} as any);
query: toQueryRecord(req.query),
});

return handle(res, result);
}
Expand All @@ -52,8 +69,8 @@ export async function getAuthEventTimeseries(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
query: req.query as any,
} as any);
query: toQueryRecord(req.query),
});

return handle(res, result);
}
Expand All @@ -70,7 +87,7 @@ export async function getLoginStats(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
Expand All @@ -87,7 +104,7 @@ export async function getSecurityAnomalies(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
Expand All @@ -104,7 +121,7 @@ export async function getDashboardMetrics(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
Expand All @@ -121,8 +138,8 @@ export async function getGroupedEventSummary(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
query: req.query as any,
} as any);
query: toQueryRecord(req.query),
});

return handle(res, result);
}
2 changes: 1 addition & 1 deletion packages/express/src/handlers/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function login(
preAuthCookieName: opts.preAuthCookieName!,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any,
},
);

if (result.setCookies) {
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/me.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export async function me(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

if (result.clearCookies) {
const signer = buildCookieSigner(opts);
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/pollMagicLinkConfirmation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function pollMagicLinkConfirmation(
{
authorization,
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any,
},
{
authServerUrl: opts.authServerUrl,
audience: opts.audience,
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export async function register(
serviceAuthorization: opts.messaging
? buildInternalServiceAuthorization(opts)
: buildProxyServiceAuthorization(opts),
} as any,
},
);

if (result.setCookies) {
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/requestMagicLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function requestMagicLink(
serviceAuthorization: opts.messaging
? buildInternalServiceAuthorization(opts)
: buildProxyServiceAuthorization(opts),
} as any,
},
);

if (result.error) {
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/handlers/requestOtp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export async function requestOtp(
serviceAuthorization: opts.messaging
? buildInternalServiceAuthorization(opts)
: buildProxyServiceAuthorization(opts),
} as any,
},
);

if (result.error) {
Expand Down
6 changes: 3 additions & 3 deletions packages/express/src/handlers/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function listSessions(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
Expand All @@ -48,7 +48,7 @@ export async function revokeSession(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
Expand All @@ -65,7 +65,7 @@ export async function revokeAllSessions(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

return handle(res, result);
}
6 changes: 3 additions & 3 deletions packages/express/src/handlers/systemConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function getAvailableRoles(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

if (result.error) {
return res.status(result.status).json({ error: result.error });
Expand All @@ -45,7 +45,7 @@ export async function getSystemConfigAdmin(
authorization,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

if (result.error) {
return res.status(result.status).json({ error: result.error });
Expand All @@ -67,7 +67,7 @@ export async function updateSystemConfig(
payload: req.body,
serviceAuthorization: buildProxyServiceAuthorization(opts),
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any);
});

if (result.error) {
return res.status(result.status).json({ error: result.error });
Expand Down
2 changes: 1 addition & 1 deletion packages/express/src/middleware/ensureCookies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function createEnsureCookiesMiddleware(
audience: opts.audience,
keyId: opts.keyId,
forwardedClientIp: buildForwardedClientIp(req, opts.resolveClientIp),
} as any,
},
);

applyResult(res, req, result, opts, cookieSigner);
Expand Down
Loading