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
13 changes: 6 additions & 7 deletions app/auth/login/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@ export async function GET(req: NextRequest) {
if (!coinpayConfigured()) {
return new NextResponse("CoinPay login is not configured yet.", { status: 503 });
}
const mode = req.nextUrl.searchParams.get("mode") === "connect" ? "connect" : "login";
if (mode === "connect") {
const s = readSession(req.cookies.get(SESSION_COOKIE)?.value);
if (!s?.sub?.startsWith("acct:")) {
return NextResponse.redirect(new URL("/login", req.nextUrl.origin));
}
}
const secure = requestIsHttps(req);
// Send the IdP back to the host the user is actually on, so the host-only
// pending cookies set below are still readable at the callback.
const origin = resolveOrigin(requestHosts(req.headers), secure);
const mode = req.nextUrl.searchParams.get("mode") === "connect" ? "connect" : "login";
if (mode === "connect") {
const s = readSession(req.cookies.get(SESSION_COOKIE)?.value);
// req.nextUrl.origin is the container's own address behind the proxy.
if (!s?.sub?.startsWith("acct:")) return NextResponse.redirect(`${origin}/login`);
}
const { verifier, challenge, state, nonce } = makePkce();
const res = NextResponse.redirect(authorizeUrl(challenge, state, redirectUriFor(origin), nonce));
const opts = { httpOnly: true, sameSite: "lax" as const, secure, path: "/", maxAge: 600 };
Expand Down
5 changes: 3 additions & 2 deletions tests/coinpay-signin.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ test("start sends PKCE S256, state and nonce; connect needs a password session",
assert.ok(loc.searchParams.get("state") && loc.searchParams.get("nonce") && loc.searchParams.get("code_challenge"));
assert.equal(loc.searchParams.get("redirect_uri"), "https://moshcoding.com/auth/coinpay/callback");

const noSession = await loginRoute.GET(new NextRequest("https://moshcoding.com/auth/login?mode=connect", { headers: { host: "moshcoding.com" } }));
assert.equal(new URL(noSession.headers.get("location")).pathname, "/login");
// behind the proxy the request URL is the container's own address
const noSession = await loginRoute.GET(new NextRequest("http://localhost:8080/auth/login?mode=connect", { headers: { host: "moshcoding.com", "x-forwarded-proto": "https" } }));
assert.equal(noSession.headers.get("location"), "https://moshcoding.com/login");
});

function callbackReq({ state = "s1", cookieState = "s1", mode, session } = {}) {
Expand Down
Loading