diff --git a/app/routes/api.oauth.token.tsx b/app/routes/api.oauth.token.tsx new file mode 100644 index 0000000..50e540d --- /dev/null +++ b/app/routes/api.oauth.token.tsx @@ -0,0 +1,47 @@ +import { type ActionFunctionArgs, json } from "@remix-run/node"; +import { OAuthClient } from "~/api/login/oauth-client"; +import { OAUTH_CONFIG } from "~/config/api-config"; + +/** + * 这个Action作为获取OAuth Access Token的服务器端代理。 + * 它接收来自前端回调的`code`,然后在后端安全地换取令牌, + * 以避免在网络策略限制服务器直接访问外部服务时出现问题。 + */ +export async function action({ request }: ActionFunctionArgs) { + // 1. 只允许POST请求 + if (request.method !== "POST") { + return json({ success: false, error: "Method Not Allowed" }, { status: 405 }); + } + + try { + // 2. 从请求体中获取`code` + const { code } = await request.json(); + + if (!code || typeof code !== 'string') { + return json({ success: false, error: "Missing or invalid 'code' in request body" }, { status: 400 }); + } + + console.log("🔧 [/api/oauth/token] 收到代理请求, code:", code ? `${code.substring(0, 10)}...` : null); + + // 3. 在服务器端使用OAuthClient安全地获取访问令牌 + const oauthClient = new OAuthClient(OAUTH_CONFIG); + const tokenResponse = await oauthClient.getAccessToken(code); + + // 4. 处理来自IDaaS服务器的响应 + if (!tokenResponse) { + console.error("❌ [/api/oauth/token] 从IDaaS获取访问令牌失败。"); + // 502 Bad Gateway 表示上游服务器(IDaaS)响应无效 + return json({ success: false, error: "Failed to get access token from IDaaS" }, { status: 502 }); + } + + console.log("✅ [/api/oauth/token] 已通过代理成功获取令牌。"); + + // 5. 将成功的令牌响应返回给调用方 (callback.tsx) + return json({ success: true, ...tokenResponse }); + + } catch (error) { + console.error("❌ [/api/oauth/token] 代理API发生意外错误:", error); + const errorMessage = error instanceof Error ? error.message : "An unknown error occurred."; + return json({ success: false, error: "Proxy internal error", details: errorMessage }, { status: 500 }); + } +} \ No newline at end of file diff --git a/app/routes/api.oauth.userinfo.tsx b/app/routes/api.oauth.userinfo.tsx new file mode 100644 index 0000000..a2c81ec --- /dev/null +++ b/app/routes/api.oauth.userinfo.tsx @@ -0,0 +1,40 @@ +import { type ActionFunctionArgs, json } from "@remix-run/node"; +import { OAuthClient } from "~/api/login/oauth-client"; +import { OAUTH_CONFIG } from "~/config/api-config"; + +/** + * 这个Action作为获取用户信息的服务器端代理。 + * 它接收来自前端的`access_token`,然后在后端安全地获取用户信息。 + */ +export async function action({ request }: ActionFunctionArgs) { + if (request.method !== "POST") { + return json({ success: false, error: "Method Not Allowed" }, { status: 405 }); + } + + try { + const { accessToken } = await request.json(); + + if (!accessToken || typeof accessToken !== 'string') { + return json({ success: false, error: "Missing or invalid 'accessToken' in request body" }, { status: 400 }); + } + + console.log("🔧 [/api/oauth/userinfo] 收到代理请求。"); + + const oauthClient = new OAuthClient(OAUTH_CONFIG); + const userInfoResponse = await oauthClient.getUserInfo(accessToken); + + if (!userInfoResponse || !userInfoResponse.success) { + console.error("❌ [/api/oauth/userinfo] 从IDaaS获取用户信息失败。"); + return json({ success: false, error: "Failed to get user info from IDaaS" }, { status: 502 }); + } + + console.log("✅ [/api/oauth/userinfo] 已通过代理成功获取用户信息。"); + + return json({ success: true, data: userInfoResponse.data }); + + } catch (error) { + console.error("❌ [/api/oauth/userinfo] 代理API发生意外错误:", error); + const errorMessage = error instanceof Error ? error.message : "An unknown error occurred."; + return json({ success: false, error: "Proxy internal error", details: errorMessage }, { status: 500 }); + } +} \ No newline at end of file