mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 13:35:07 +00:00
find sessions for loginHint, send to select account
This commit is contained in:
@@ -20,7 +20,13 @@ async function loadSessions(): Promise<Session[]> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page({
|
||||||
|
searchParams,
|
||||||
|
}: {
|
||||||
|
searchParams: Record<string | number | symbol, string | undefined>;
|
||||||
|
}) {
|
||||||
|
const authRequestId = searchParams?.authRequestId;
|
||||||
|
|
||||||
let sessions = await loadSessions();
|
let sessions = await loadSessions();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -29,7 +35,7 @@ export default async function Page() {
|
|||||||
<p className="ztdl-p mb-6 block">Use your ZITADEL Account</p>
|
<p className="ztdl-p mb-6 block">Use your ZITADEL Account</p>
|
||||||
|
|
||||||
<div className="flex flex-col w-full space-y-2">
|
<div className="flex flex-col w-full space-y-2">
|
||||||
<SessionsList sessions={sessions} />
|
<SessionsList sessions={sessions} authRequestId={authRequestId} />
|
||||||
<Link href="/loginname">
|
<Link href="/loginname">
|
||||||
<div className="flex flex-row items-center py-3 px-4 hover:bg-black/10 dark:hover:bg-white/10 rounded-md transition-all">
|
<div className="flex flex-row items-center py-3 px-4 hover:bg-black/10 dark:hover:bg-white/10 rounded-md transition-all">
|
||||||
<div className="w-8 h-8 mr-4 flex flex-row justify-center items-center rounded-full bg-black/5 dark:bg-white/5">
|
<div className="w-8 h-8 mr-4 flex flex-row justify-center items-center rounded-full bg-black/5 dark:bg-white/5">
|
||||||
|
|||||||
@@ -1,21 +1,36 @@
|
|||||||
import { getAuthRequest, listSessions, server } from "#/lib/zitadel";
|
import {
|
||||||
import { getAllSessionIds } from "#/utils/cookies";
|
createCallback,
|
||||||
import { Session } from "@zitadel/server";
|
getAuthRequest,
|
||||||
|
listSessions,
|
||||||
|
server,
|
||||||
|
} from "#/lib/zitadel";
|
||||||
|
import { SessionCookie, getAllSessions } from "#/utils/cookies";
|
||||||
|
import { Session, AuthRequest, Prompt } from "@zitadel/server";
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
async function loadSessions(): Promise<Session[]> {
|
async function loadSessions(ids: string[]): Promise<Session[]> {
|
||||||
const ids: string[] = await getAllSessionIds();
|
|
||||||
|
|
||||||
if (ids && ids.length) {
|
|
||||||
const response = await listSessions(
|
const response = await listSessions(
|
||||||
server,
|
server,
|
||||||
ids.filter((id: string | undefined) => !!id)
|
ids.filter((id: string | undefined) => !!id)
|
||||||
);
|
);
|
||||||
return response?.sessions ?? [];
|
return response?.sessions ?? [];
|
||||||
} else {
|
|
||||||
console.info("No session cookie found.");
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function findSession(
|
||||||
|
sessions: Session[],
|
||||||
|
authRequest: AuthRequest
|
||||||
|
): Session | undefined {
|
||||||
|
if (authRequest.hintUserId) {
|
||||||
|
console.log(`find session for hintUserId: ${authRequest.hintUserId}`);
|
||||||
|
return sessions.find((s) => s.factors?.user?.id === authRequest.hintUserId);
|
||||||
|
}
|
||||||
|
if (authRequest.loginHint) {
|
||||||
|
console.log(`find session for loginHint: ${authRequest.loginHint}`);
|
||||||
|
return sessions.find(
|
||||||
|
(s) => s.factors?.user?.loginName === authRequest.loginHint
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
export async function GET(request: NextRequest) {
|
||||||
@@ -23,17 +38,67 @@ export async function GET(request: NextRequest) {
|
|||||||
const authRequestId = searchParams.get("authRequest");
|
const authRequestId = searchParams.get("authRequest");
|
||||||
|
|
||||||
if (authRequestId) {
|
if (authRequestId) {
|
||||||
const response = await getAuthRequest(server, { authRequestId });
|
const { authRequest } = await getAuthRequest(server, { authRequestId });
|
||||||
const sessions = await loadSessions();
|
const sessionCookies: SessionCookie[] = await getAllSessions();
|
||||||
if (sessions.length) {
|
const ids = sessionCookies.map((s) => s.id);
|
||||||
return NextResponse.json(sessions);
|
|
||||||
|
let sessions: Session[] = [];
|
||||||
|
if (ids && ids.length) {
|
||||||
|
sessions = await loadSessions(ids);
|
||||||
|
} else {
|
||||||
|
console.info("No session cookie found.");
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// use existing session and hydrate it for oidc
|
||||||
|
if (authRequest && sessions.length) {
|
||||||
|
// if some accounts are available for selection and select_account is set
|
||||||
|
if (authRequest && authRequest.prompt === Prompt.PROMPT_SELECT_ACCOUNT) {
|
||||||
|
const accountsUrl = new URL("/accounts", request.url);
|
||||||
|
if (authRequest?.id) {
|
||||||
|
accountsUrl.searchParams.set("authRequestId", authRequest?.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.redirect(accountsUrl);
|
||||||
|
} else {
|
||||||
|
// check for loginHint, userId hint sessions
|
||||||
|
let selectedSession = findSession(sessions, authRequest);
|
||||||
|
|
||||||
|
if (!selectedSession) {
|
||||||
|
selectedSession = sessions[0]; // TODO: remove
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedSession && selectedSession.id) {
|
||||||
|
const cookie = sessionCookies.find(
|
||||||
|
(cookie) => cookie.id === selectedSession?.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (cookie && cookie.id && cookie.token) {
|
||||||
|
const session = {
|
||||||
|
sessionId: cookie?.id,
|
||||||
|
sessionToken: cookie?.token,
|
||||||
|
};
|
||||||
|
const { callbackUrl } = await createCallback(server, {
|
||||||
|
authRequestId,
|
||||||
|
session,
|
||||||
|
});
|
||||||
|
return NextResponse.redirect(callbackUrl);
|
||||||
|
} else {
|
||||||
|
const accountsUrl = new URL("/accounts", request.url);
|
||||||
|
if (authRequest?.id) {
|
||||||
|
accountsUrl.searchParams.set("authRequestId", authRequest?.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.redirect(accountsUrl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NextResponse.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const loginNameUrl = new URL("/loginname", request.url);
|
const loginNameUrl = new URL("/loginname", request.url);
|
||||||
if (response.authRequest?.id) {
|
if (authRequest?.id) {
|
||||||
loginNameUrl.searchParams.set(
|
loginNameUrl.searchParams.set("authRequestId", authRequest?.id);
|
||||||
"authRequestId",
|
|
||||||
response.authRequest?.id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NextResponse.redirect(loginNameUrl);
|
return NextResponse.redirect(loginNameUrl);
|
||||||
|
|||||||
@@ -248,13 +248,11 @@ export async function getAuthRequest(
|
|||||||
|
|
||||||
export async function createCallback(
|
export async function createCallback(
|
||||||
server: ZitadelServer,
|
server: ZitadelServer,
|
||||||
{ authRequestId }: CreateCallbackRequest
|
req: CreateCallbackRequest
|
||||||
): Promise<CreateCallbackResponse> {
|
): Promise<CreateCallbackResponse> {
|
||||||
const oidcService = oidc.getOidc(server);
|
const oidcService = oidc.getOidc(server);
|
||||||
|
|
||||||
return oidcService.createCallback({
|
return oidcService.createCallback(req);
|
||||||
authRequestId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyEmail(
|
export async function verifyEmail(
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ import { XCircleIcon } from "@heroicons/react/24/outline";
|
|||||||
export default function SessionItem({
|
export default function SessionItem({
|
||||||
session,
|
session,
|
||||||
reload,
|
reload,
|
||||||
|
authRequestId,
|
||||||
}: {
|
}: {
|
||||||
session: Session;
|
session: Session;
|
||||||
reload: () => void;
|
reload: () => void;
|
||||||
|
authRequestId?: string;
|
||||||
}) {
|
}) {
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
@@ -52,10 +54,18 @@ export default function SessionItem({
|
|||||||
loginName: session.factors?.user?.loginName as string,
|
loginName: session.factors?.user?.loginName as string,
|
||||||
})
|
})
|
||||||
: `/loginname?` +
|
: `/loginname?` +
|
||||||
new URLSearchParams({
|
new URLSearchParams(
|
||||||
|
authRequestId
|
||||||
|
? {
|
||||||
loginName: session.factors?.user?.loginName as string,
|
loginName: session.factors?.user?.loginName as string,
|
||||||
submit: "true",
|
submit: "true",
|
||||||
})
|
authRequestId,
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
loginName: session.factors?.user?.loginName as string,
|
||||||
|
submit: "true",
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
className="group flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light hover:shadow-lg dark:hover:bg-white/10 py-2 px-4 rounded-md transition-all"
|
className="group flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light hover:shadow-lg dark:hover:bg-white/10 py-2 px-4 rounded-md transition-all"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ import { useEffect, useState } from "react";
|
|||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
sessions: Session[];
|
sessions: Session[];
|
||||||
|
authRequestId?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function SessionsList({ sessions }: Props) {
|
export default function SessionsList({ sessions, authRequestId }: Props) {
|
||||||
const [list, setList] = useState<Session[]>(sessions);
|
const [list, setList] = useState<Session[]>(sessions);
|
||||||
return sessions ? (
|
return sessions ? (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
@@ -19,6 +20,7 @@ export default function SessionsList({ sessions }: Props) {
|
|||||||
return (
|
return (
|
||||||
<SessionItem
|
<SessionItem
|
||||||
session={session}
|
session={session}
|
||||||
|
authRequestId={authRequestId}
|
||||||
reload={() => {
|
reload={() => {
|
||||||
setList(list.filter((s) => s.id !== session.id));
|
setList(list.filter((s) => s.id !== session.id));
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ export {
|
|||||||
CreateCallbackResponse,
|
CreateCallbackResponse,
|
||||||
} from "./proto/server/zitadel/oidc/v2alpha/oidc_service";
|
} from "./proto/server/zitadel/oidc/v2alpha/oidc_service";
|
||||||
|
|
||||||
|
export {
|
||||||
|
AuthRequest,
|
||||||
|
Prompt,
|
||||||
|
} from "./proto/server/zitadel/oidc/v2alpha/authorization";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Session,
|
Session,
|
||||||
Factors,
|
Factors,
|
||||||
|
|||||||
Reference in New Issue
Block a user