mirror of
https://github.com/profullstack/logicsrc.git
synced 2026-08-13 22:37:29 +00:00
Require CoinPay userinfo identity (#21)
This commit is contained in:
parent
63ccad6d2a
commit
14fe9d608f
2 changed files with 36 additions and 1 deletions
|
|
@ -392,6 +392,34 @@ describe("CoinPay OAuth", () => {
|
||||||
user: { provider: "coinpay", sub: "merchant-123", email: "merchant@example.com", name: "Merchant User" }
|
user: { provider: "coinpay", sub: "merchant-123", email: "merchant@example.com", name: "Merchant User" }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not create a session when userinfo omits the subject", async () => {
|
||||||
|
process.env.COINPAY_OAUTH_ISSUER = "https://coinpayportal.example";
|
||||||
|
process.env.COINPAY_OAUTH_CLIENT_ID = "cp_test_client";
|
||||||
|
process.env.COINPAY_OAUTH_CLIENT_SECRET = "cps_test_secret";
|
||||||
|
process.env.COINPAY_OAUTH_REDIRECT_URI = "https://logicsrc.com/api/oauth/coinpay/callback";
|
||||||
|
|
||||||
|
vi.spyOn(globalThis, "fetch").mockImplementation(async (input) => {
|
||||||
|
const url = typeof input === "string" ? input : input.toString();
|
||||||
|
if (url.includes("/api/oauth/token")) {
|
||||||
|
return jsonResponse({ access_token: "access_token_123", token_type: "Bearer", scope: "openid profile email" });
|
||||||
|
}
|
||||||
|
if (url.includes("/api/oauth/userinfo")) {
|
||||||
|
return jsonResponse({ email: "merchant@example.com", name: "Merchant User" });
|
||||||
|
}
|
||||||
|
throw new Error(`unexpected fetch ${url}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const callback = await oauthCallback(
|
||||||
|
new NextRequest("http://localhost/api/oauth/coinpay/callback?code=auth_code_123&state=state_123", {
|
||||||
|
headers: { cookie: "logicsrc_coinpay_oauth_state=state_123" }
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(callback.status).toBe(302);
|
||||||
|
expect(callback.headers.get("location")).toBe("/?coinpay_oauth=error&error=userinfo_failed");
|
||||||
|
expect(callback.headers.getSetCookie().some((cookie) => cookie.startsWith("logicsrc_coinpay_session="))).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("session signing", () => {
|
describe("session signing", () => {
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,17 @@ export async function GET(request: NextRequest) {
|
||||||
});
|
});
|
||||||
const userText = await userResponse.text();
|
const userText = await userResponse.text();
|
||||||
const userInfo = userResponse.ok ? parseJson(userText) : {};
|
const userInfo = userResponse.ok ? parseJson(userText) : {};
|
||||||
|
if (!userResponse.ok || typeof userInfo.sub !== "string" || userInfo.sub.trim() === "") {
|
||||||
|
console.error("[coinpay-oauth] userinfo failed", {
|
||||||
|
status: userResponse.status,
|
||||||
|
error: userResponse.ok ? "missing_sub" : userText.slice(0, 160)
|
||||||
|
});
|
||||||
|
return redirectWithOAuthStatus("error", "userinfo_failed");
|
||||||
|
}
|
||||||
|
|
||||||
const session = signSession({
|
const session = signSession({
|
||||||
provider: "coinpay",
|
provider: "coinpay",
|
||||||
sub: typeof userInfo.sub === "string" ? userInfo.sub : null,
|
sub: userInfo.sub,
|
||||||
email: typeof userInfo.email === "string" ? userInfo.email : null,
|
email: typeof userInfo.email === "string" ? userInfo.email : null,
|
||||||
name: typeof userInfo.name === "string" ? userInfo.name : null,
|
name: typeof userInfo.name === "string" ? userInfo.name : null,
|
||||||
scope: typeof tokenPayload.scope === "string" ? tokenPayload.scope : config.scopes,
|
scope: typeof tokenPayload.scope === "string" ? tokenPayload.scope : config.scopes,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue