feat(auth): validate agent context upstream
This commit is contained in:
+51
-20
@@ -1,6 +1,7 @@
|
||||
import { Router } from "express";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getAgentAuthContext } from "../auth/agentAuth.js";
|
||||
import {
|
||||
agentModelOptions,
|
||||
isSupportedModel,
|
||||
@@ -18,6 +19,7 @@ import { type ResultReferenceResolver } from "../results/resolver.js";
|
||||
import {
|
||||
type OpencodeRuntimeAdapter,
|
||||
} from "../runtime/opencode.js";
|
||||
import { getRuntimeSessionContext } from "../runtime/sessionContext.js";
|
||||
import { type ChatSessionBridge } from "../chat/sessionBridge.js";
|
||||
import { type SessionRecord } from "../sessions/metadataStore.js";
|
||||
import { toActorKey, toProjectKey } from "../utils/fileStore.js";
|
||||
@@ -139,8 +141,9 @@ export const buildChatRouter = (
|
||||
return;
|
||||
}
|
||||
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const requestedSessionId = parsed.data.session_id?.trim();
|
||||
@@ -166,8 +169,9 @@ export const buildChatRouter = (
|
||||
});
|
||||
|
||||
chatRouter.get("/sessions", async (req, res) => {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const records = await sessionMetadataStore.list({
|
||||
@@ -192,8 +196,9 @@ export const buildChatRouter = (
|
||||
|
||||
chatRouter.get("/session/:sessionId", async (req, res) => {
|
||||
const sessionId = req.params.sessionId?.trim();
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
if (!sessionId) {
|
||||
@@ -235,8 +240,9 @@ export const buildChatRouter = (
|
||||
|
||||
chatRouter.get("/session/:sessionId/stream", async (req, res) => {
|
||||
const sessionId = req.params.sessionId?.trim();
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
if (!sessionId) {
|
||||
@@ -305,8 +311,9 @@ export const buildChatRouter = (
|
||||
typeof req.body?.is_title_manually_edited === "boolean"
|
||||
? req.body.is_title_manually_edited
|
||||
: undefined;
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
if (!sessionId || !title) {
|
||||
@@ -344,8 +351,9 @@ export const buildChatRouter = (
|
||||
|
||||
chatRouter.delete("/session/:sessionId", async (req, res) => {
|
||||
const sessionId = req.params.sessionId?.trim();
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
if (!sessionId) {
|
||||
@@ -398,9 +406,10 @@ export const buildChatRouter = (
|
||||
}
|
||||
|
||||
try {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const traceId = req.header("x-trace-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const userId = authContext.userId;
|
||||
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
@@ -497,13 +506,11 @@ export const buildChatRouter = (
|
||||
}
|
||||
|
||||
try {
|
||||
const authHeader = req.header("authorization");
|
||||
const accessToken = authHeader?.startsWith("Bearer ")
|
||||
? authHeader.slice("Bearer ".length)
|
||||
: authHeader;
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const accessToken = authContext.accessToken;
|
||||
const projectId = authContext.projectId;
|
||||
const traceId = req.header("x-trace-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const requestedSessionId = parsed.data.session_id?.trim();
|
||||
@@ -520,6 +527,7 @@ export const buildChatRouter = (
|
||||
accessToken,
|
||||
projectId,
|
||||
traceId,
|
||||
tokenExpiresAt: authContext.tokenExpiresAt,
|
||||
userId,
|
||||
});
|
||||
const { record: ensuredSessionRecord, created: sessionCreated } =
|
||||
@@ -676,6 +684,19 @@ export const buildChatRouter = (
|
||||
progress: completeBackendProgress(message.progress),
|
||||
todos: cancelBackendTodos(message.todos),
|
||||
}));
|
||||
} else if (event === "auth_required") {
|
||||
activeRun.status = "error";
|
||||
lastRunStatuses.set(clientSessionId, "error");
|
||||
activeRun.messages = updateLastAssistantMessage(activeRun.messages, (message) => ({
|
||||
...message,
|
||||
content:
|
||||
typeof data.message === "string"
|
||||
? `⚠️ **${data.message}**`
|
||||
: "⚠️ **登录态已过期,请刷新登录后重试**",
|
||||
isError: true,
|
||||
progress: completeBackendProgress(message.progress),
|
||||
todos: cancelBackendTodos(message.todos),
|
||||
}));
|
||||
} else if (event === "permission_request") {
|
||||
const payload = data as PermissionRequestPayload;
|
||||
activeRun.pendingPermissions.set(payload.request_id, payload);
|
||||
@@ -804,6 +825,16 @@ export const buildChatRouter = (
|
||||
logger.warn({ err: error, sessionId: clientSessionId }, "failed to persist chat stream state");
|
||||
});
|
||||
|
||||
const latestRuntimeContext = getRuntimeSessionContext(binding.sessionId);
|
||||
if (latestRuntimeContext?.authExpired) {
|
||||
publish("auth_required", {
|
||||
session_id: clientSessionId,
|
||||
reason: latestRuntimeContext.authExpired.reason,
|
||||
message: latestRuntimeContext.authExpired.message,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!streamResult.aborted && !streamResult.failed) {
|
||||
const messages = await runtime.messages(binding.sessionId, 60);
|
||||
const assistantMessage = [...messages]
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { type Router } from "express";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getAgentAuthContext } from "../auth/agentAuth.js";
|
||||
import { type ChatSessionBridge } from "../chat/sessionBridge.js";
|
||||
import { logger } from "../logger.js";
|
||||
import { type ResultReferenceResolver } from "../results/resolver.js";
|
||||
@@ -46,20 +47,14 @@ export const registerChatAuxiliaryRoutes = (
|
||||
) => {
|
||||
chatRouter.get("/render-ref/:renderRef", async (req, res) => {
|
||||
const renderRef = req.params.renderRef?.trim();
|
||||
const userId = req.header("x-user-id")?.trim();
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const userId = authContext.userId;
|
||||
const projectId = authContext.projectId;
|
||||
const clientSessionId =
|
||||
typeof req.query.session_id === "string"
|
||||
? req.query.session_id.trim()
|
||||
: undefined;
|
||||
|
||||
if (!userId) {
|
||||
res.status(400).json({
|
||||
message: "x-user-id is required",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!renderRef) {
|
||||
res.status(400).json({
|
||||
message: "render_ref is required",
|
||||
@@ -98,8 +93,9 @@ export const registerChatAuxiliaryRoutes = (
|
||||
}
|
||||
|
||||
try {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const sessionRecord = await sessionMetadataStore.get(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { type Router } from "express";
|
||||
import { z } from "zod";
|
||||
|
||||
import { getAgentAuthContext } from "../auth/agentAuth.js";
|
||||
import { logger } from "../logger.js";
|
||||
import { type OpencodeRuntimeAdapter } from "../runtime/opencode.js";
|
||||
import { type SessionMetadataStore } from "../sessions/metadataStore.js";
|
||||
@@ -64,8 +65,9 @@ export const registerChatInteractionRoutes = (
|
||||
}
|
||||
|
||||
try {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const sessionRecord = await sessionMetadataStore.get(
|
||||
@@ -188,8 +190,9 @@ export const registerChatInteractionRoutes = (
|
||||
}
|
||||
|
||||
try {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const sessionRecord = await sessionMetadataStore.get(
|
||||
@@ -319,8 +322,9 @@ export const registerChatInteractionRoutes = (
|
||||
}
|
||||
|
||||
try {
|
||||
const projectId = req.header("x-project-id") ?? undefined;
|
||||
const userId = req.header("x-user-id") ?? undefined;
|
||||
const authContext = getAgentAuthContext(req);
|
||||
const projectId = authContext.projectId;
|
||||
const userId = authContext.userId;
|
||||
const actorKey = toActorKey(userId);
|
||||
const projectKey = toProjectKey(projectId);
|
||||
const sessionRecord = await sessionMetadataStore.get(
|
||||
|
||||
Reference in New Issue
Block a user