mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 02:02:23 +00:00
form post
This commit is contained in:
@@ -7,6 +7,7 @@ import { getServiceUrlFromHeaders } from "@/lib/service";
|
|||||||
import { findValidSession } from "@/lib/session";
|
import { findValidSession } from "@/lib/session";
|
||||||
import {
|
import {
|
||||||
createCallback,
|
createCallback,
|
||||||
|
createResponse,
|
||||||
getActiveIdentityProviders,
|
getActiveIdentityProviders,
|
||||||
getAuthRequest,
|
getAuthRequest,
|
||||||
getOrgsByDomain,
|
getOrgsByDomain,
|
||||||
@@ -15,14 +16,12 @@ import {
|
|||||||
startIdentityProviderFlow,
|
startIdentityProviderFlow,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { create } from "@zitadel/client";
|
import { create } from "@zitadel/client";
|
||||||
import {
|
import { Prompt } from "@zitadel/proto/zitadel/oidc/v2/authorization_pb";
|
||||||
AuthRequest,
|
|
||||||
Prompt,
|
|
||||||
} from "@zitadel/proto/zitadel/oidc/v2/authorization_pb";
|
|
||||||
import {
|
import {
|
||||||
CreateCallbackRequestSchema,
|
CreateCallbackRequestSchema,
|
||||||
SessionSchema,
|
SessionSchema,
|
||||||
} from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb";
|
} from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb";
|
||||||
|
import { CreateResponseRequestSchema } from "@zitadel/proto/zitadel/saml/v2/saml_service_pb";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
@@ -33,19 +32,17 @@ export const fetchCache = "default-no-store";
|
|||||||
|
|
||||||
const gotoAccounts = ({
|
const gotoAccounts = ({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
requestId,
|
||||||
organization,
|
organization,
|
||||||
idPrefix,
|
|
||||||
}: {
|
}: {
|
||||||
request: NextRequest;
|
request: NextRequest;
|
||||||
authRequest: AuthRequest;
|
requestId: string;
|
||||||
organization: string;
|
organization?: string;
|
||||||
idPrefix: string;
|
|
||||||
}): NextResponse<unknown> => {
|
}): NextResponse<unknown> => {
|
||||||
const accountsUrl = new URL("/accounts", request.url);
|
const accountsUrl = new URL("/accounts", request.url);
|
||||||
|
|
||||||
if (authRequest?.id) {
|
if (requestId) {
|
||||||
accountsUrl.searchParams.set("requestId", `${idPrefix}${authRequest.id}`);
|
accountsUrl.searchParams.set("requestId", requestId);
|
||||||
}
|
}
|
||||||
if (organization) {
|
if (organization) {
|
||||||
accountsUrl.searchParams.set("organization", organization);
|
accountsUrl.searchParams.set("organization", organization);
|
||||||
@@ -59,7 +56,6 @@ async function loadSessions({
|
|||||||
ids,
|
ids,
|
||||||
}: {
|
}: {
|
||||||
serviceUrl: string;
|
serviceUrl: string;
|
||||||
|
|
||||||
ids: string[];
|
ids: string[];
|
||||||
}): Promise<Session[]> {
|
}): Promise<Session[]> {
|
||||||
const response = await listSessions({
|
const response = await listSessions({
|
||||||
@@ -177,7 +173,6 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
const identityProviders = await getActiveIdentityProviders({
|
const identityProviders = await getActiveIdentityProviders({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
|
||||||
orgId: organization ? organization : undefined,
|
orgId: organization ? organization : undefined,
|
||||||
}).then((resp) => {
|
}).then((resp) => {
|
||||||
return resp.identityProviders;
|
return resp.identityProviders;
|
||||||
@@ -203,7 +198,6 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
return startIdentityProviderFlow({
|
return startIdentityProviderFlow({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
|
||||||
idpId,
|
idpId,
|
||||||
urls: {
|
urls: {
|
||||||
successUrl:
|
successUrl:
|
||||||
@@ -243,9 +237,8 @@ export async function GET(request: NextRequest) {
|
|||||||
if (authRequest.prompt.includes(Prompt.SELECT_ACCOUNT)) {
|
if (authRequest.prompt.includes(Prompt.SELECT_ACCOUNT)) {
|
||||||
return gotoAccounts({
|
return gotoAccounts({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
requestId: `oidc_${authRequest.id}`,
|
||||||
organization,
|
organization,
|
||||||
idPrefix: "oidc_",
|
|
||||||
});
|
});
|
||||||
} else if (authRequest.prompt.includes(Prompt.LOGIN)) {
|
} else if (authRequest.prompt.includes(Prompt.LOGIN)) {
|
||||||
/**
|
/**
|
||||||
@@ -300,7 +293,6 @@ export async function GET(request: NextRequest) {
|
|||||||
**/
|
**/
|
||||||
const selectedSession = await findValidSession({
|
const selectedSession = await findValidSession({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
|
||||||
sessions,
|
sessions,
|
||||||
authRequest,
|
authRequest,
|
||||||
});
|
});
|
||||||
@@ -330,7 +322,6 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
const { callbackUrl } = await createCallback({
|
const { callbackUrl } = await createCallback({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
|
||||||
req: create(CreateCallbackRequestSchema, {
|
req: create(CreateCallbackRequestSchema, {
|
||||||
authRequestId: requestId.replace("oidc_", ""),
|
authRequestId: requestId.replace("oidc_", ""),
|
||||||
callbackKind: {
|
callbackKind: {
|
||||||
@@ -351,9 +342,8 @@ export async function GET(request: NextRequest) {
|
|||||||
if (!selectedSession || !selectedSession.id) {
|
if (!selectedSession || !selectedSession.id) {
|
||||||
return gotoAccounts({
|
return gotoAccounts({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
requestId: `oidc_${authRequest.id}`,
|
||||||
organization,
|
organization,
|
||||||
idPrefix: "oidc_",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,9 +354,8 @@ export async function GET(request: NextRequest) {
|
|||||||
if (!cookie || !cookie.id || !cookie.token) {
|
if (!cookie || !cookie.id || !cookie.token) {
|
||||||
return gotoAccounts({
|
return gotoAccounts({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
requestId: `oidc_${authRequest.id}`,
|
||||||
organization,
|
organization,
|
||||||
idPrefix: "oidc_",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,18 +384,16 @@ export async function GET(request: NextRequest) {
|
|||||||
);
|
);
|
||||||
return gotoAccounts({
|
return gotoAccounts({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
|
||||||
organization,
|
organization,
|
||||||
idPrefix: "oidc_",
|
requestId: `oidc_${authRequest.id}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return gotoAccounts({
|
return gotoAccounts({
|
||||||
request,
|
request,
|
||||||
authRequest,
|
requestId: `oidc_${authRequest.id}`,
|
||||||
organization,
|
organization,
|
||||||
idPrefix: "oidc_",
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,6 +419,107 @@ export async function GET(request: NextRequest) {
|
|||||||
serviceUrl,
|
serviceUrl,
|
||||||
samlRequestId: requestId.replace("saml_", ""),
|
samlRequestId: requestId.replace("saml_", ""),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!samlRequest) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "No samlRequest found" },
|
||||||
|
{ status: 400 },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedSession = await findValidSession({
|
||||||
|
serviceUrl,
|
||||||
|
sessions,
|
||||||
|
samlRequest,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!selectedSession || !selectedSession.id) {
|
||||||
|
return gotoAccounts({
|
||||||
|
request,
|
||||||
|
requestId: `saml_${samlRequest.id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const cookie = sessionCookies.find(
|
||||||
|
(cookie) => cookie.id === selectedSession.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!cookie || !cookie.id || !cookie.token) {
|
||||||
|
return gotoAccounts({
|
||||||
|
request,
|
||||||
|
requestId: `saml_${samlRequest.id}`,
|
||||||
|
// organization,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = {
|
||||||
|
sessionId: cookie.id,
|
||||||
|
sessionToken: cookie.token,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { url, binding } = await createResponse({
|
||||||
|
serviceUrl,
|
||||||
|
req: create(CreateResponseRequestSchema, {
|
||||||
|
samlRequestId: requestId.replace("saml_", ""),
|
||||||
|
responseKind: {
|
||||||
|
case: "session",
|
||||||
|
value: session,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (url && binding.case === "redirect") {
|
||||||
|
return NextResponse.redirect(url);
|
||||||
|
} else if (url && binding.case === "post") {
|
||||||
|
const formData = {
|
||||||
|
key1: "value1",
|
||||||
|
key2: "value2",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert form data to URL-encoded string
|
||||||
|
const formBody = Object.entries(formData)
|
||||||
|
.map(
|
||||||
|
([key, value]) =>
|
||||||
|
encodeURIComponent(key) + "=" + encodeURIComponent(value),
|
||||||
|
)
|
||||||
|
.join("&");
|
||||||
|
|
||||||
|
// Make a POST request to the external URL with the form data
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: formBody,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle the response from the external URL
|
||||||
|
if (response.ok) {
|
||||||
|
return NextResponse.json({
|
||||||
|
message: "SAML request completed successfully",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ error: "Failed to complete SAML request" },
|
||||||
|
{ status: response.status },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
"could not create response, redirect user to choose other account",
|
||||||
|
);
|
||||||
|
return gotoAccounts({
|
||||||
|
request,
|
||||||
|
requestId: `saml_${samlRequest.id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return gotoAccounts({
|
||||||
|
request,
|
||||||
|
requestId: `saml_${samlRequest.id}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "No authRequest nor samlRequest provided" },
|
{ error: "No authRequest nor samlRequest provided" },
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { timestampDate } from "@zitadel/client";
|
import { timestampDate } from "@zitadel/client";
|
||||||
import { AuthRequest } from "@zitadel/proto/zitadel/oidc/v2/authorization_pb";
|
import { AuthRequest } from "@zitadel/proto/zitadel/oidc/v2/authorization_pb";
|
||||||
|
import { SAMLRequest } from "@zitadel/proto/zitadel/saml/v2/authorization_pb";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { GetSessionResponse } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { GetSessionResponse } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
@@ -150,21 +151,26 @@ export async function isSessionValid({
|
|||||||
|
|
||||||
export async function findValidSession({
|
export async function findValidSession({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
|
||||||
sessions,
|
sessions,
|
||||||
authRequest,
|
authRequest,
|
||||||
|
samlRequest,
|
||||||
}: {
|
}: {
|
||||||
serviceUrl: string;
|
serviceUrl: string;
|
||||||
sessions: Session[];
|
sessions: Session[];
|
||||||
authRequest: AuthRequest;
|
authRequest?: AuthRequest;
|
||||||
|
samlRequest?: SAMLRequest;
|
||||||
}): Promise<Session | undefined> {
|
}): Promise<Session | undefined> {
|
||||||
const sessionsWithHint = sessions.filter((s) => {
|
const sessionsWithHint = sessions.filter((s) => {
|
||||||
if (authRequest.hintUserId) {
|
if (authRequest && authRequest.hintUserId) {
|
||||||
return s.factors?.user?.id === authRequest.hintUserId;
|
return s.factors?.user?.id === authRequest.hintUserId;
|
||||||
}
|
}
|
||||||
if (authRequest.loginHint) {
|
if (authRequest && authRequest.loginHint) {
|
||||||
return s.factors?.user?.loginName === authRequest.loginHint;
|
return s.factors?.user?.loginName === authRequest.loginHint;
|
||||||
}
|
}
|
||||||
|
if (samlRequest) {
|
||||||
|
// TODO: do whatever
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user