-
Notifications
You must be signed in to change notification settings - Fork 16
refactor: user tokens expiring route. #1806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: staging
Are you sure you want to change the base?
Conversation
Reviewer's guide (collapsed on small PRs)Reviewer's GuideRefactors the Sequence diagram for refactored GET /token/get/expiring routesequenceDiagram
actor Client
participant UserRouter
participant Logger
participant Database
participant Response
Client->>UserRouter: GET /token/get/expiring?expires_in&client
Note over UserRouter: Build desc = "User access tokens expiring in {expires_in} seconds"
UserRouter->>Logger: logRequestStarted(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Started, description=desc)
alt Successful query
UserRouter->>Database: _query(exp = now_in_seconds + expires_in)
Database-->>UserRouter: results (cursor)
UserRouter->>UserRouter: extra_log_info = results.toArray()
UserRouter-->>Response: send(results)
UserRouter->>Logger: logRequestSuccess(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Success, description=desc, extra={expiring_token_count: extra_log_info.length})
else Query or processing error
UserRouter->>Logger: logRequestFailure(client=req.queryParams.client, correlationId, httpVerb=GET, routePath=/token/get/expiring, status=Failure, description=desc, extra={expiring_token_count: extra_log_info.length}, error=e)
UserRouter-->>Response: handleException(e)
end
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- Calling
results.toArray()for logging afterres.send(results)may consume the cursor and change what the client receives; consider either sending the array (and logging its length) or using a cheap count-only query/log field instead. - If
expires_inis required for this route, it would be safer to validate and coercereq.queryParams.expires_into a number up front and fail fast on missing/invalid values rather than interpolating it directly into the description and query parameter.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Calling `results.toArray()` for logging after `res.send(results)` may consume the cursor and change what the client receives; consider either sending the array (and logging its length) or using a cheap count-only query/log field instead.
- If `expires_in` is required for this route, it would be safer to validate and coerce `req.queryParams.expires_in` to a number up front and fail fast on missing/invalid values rather than interpolating it directly into the description and query parameter.
## Individual Comments
### Comment 1
<location> `core/database/foxx/api/user_router.js:1163-1170` </location>
<code_context>
});
- results = g_db._query(
+ const results = g_db._query(
"for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}",
{
exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in,
},
);
res.send(results);
+ extra_log_info = results.toArray();
logger.logRequestSuccess({
- client: client?._id,
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid consuming the query cursor twice; materialize once before sending the response.
The handler sends the cursor directly with `res.send(results);` and then calls `results.toArray();`. If Foxx consumes the cursor during serialization, `toArray()` may fail or return an empty array, causing `expiring_token_count` logs to diverge from the actual response. To avoid this, materialize once and reuse:
```js
const cursor = g_db._query(/* ... */);
const results = cursor.toArray();
res.send(results);
extra_log_info = results;
```
This keeps the response and logging consistent and avoids double-consuming the cursor.
</issue_to_address>
### Comment 2
<location> `core/database/foxx/api/user_router.js:1155` </location>
<code_context>
try {
logger.logRequestStarted({
- client: user?._id,
+ client: req.queryParams.client,
correlationId: req.headers["x-correlation-id"],
httpVerb: "GET",
</code_context>
<issue_to_address>
**🚨 issue (security):** Logging `client` from a request query param may allow spoofed client identifiers.
Using `req.queryParams.client` lets any caller spoof the logged client id, which can corrupt audit trails. If `client` should reflect an authenticated user or trusted client, use an identifier from the auth context (e.g., user id, token subject, validated client id) or validate/normalize the query param before logging it.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| const results = g_db._query( | ||
| "for i in u filter i.expiration != Null && i.expiration < @exp return {id:i._id,access:i.access,refresh:i.refresh,expiration:i.expiration}", | ||
| { | ||
| exp: Math.floor(Date.now() / 1000) + req.queryParams.expires_in, | ||
| }, | ||
| ); | ||
| res.send(results); | ||
| extra_log_info = results.toArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Avoid consuming the query cursor twice; materialize once before sending the response.
The handler sends the cursor directly with res.send(results); and then calls results.toArray();. If Foxx consumes the cursor during serialization, toArray() may fail or return an empty array, causing expiring_token_count logs to diverge from the actual response. To avoid this, materialize once and reuse:
const cursor = g_db._query(/* ... */);
const results = cursor.toArray();
res.send(results);
extra_log_info = results;This keeps the response and logging consistent and avoids double-consuming the cursor.
| try { | ||
| logger.logRequestStarted({ | ||
| client: user?._id, | ||
| client: req.queryParams.client, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚨 issue (security): Logging client from a request query param may allow spoofed client identifiers.
Using req.queryParams.client lets any caller spoof the logged client id, which can corrupt audit trails. If client should reflect an authenticated user or trusted client, use an identifier from the auth context (e.g., user id, token subject, validated client id) or validate/normalize the query param before logging it.
Ticket
Description
How Has This Been Tested?
Artifacts (if appropriate):
Tasks
Summary by Sourcery
Refine the user token expiring lookup endpoint logging and response handling.
Enhancements: