mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-23 13:07:54 +00:00
login route handler
This commit is contained in:
@@ -100,6 +100,7 @@ export async function GET(request: NextRequest) {
|
||||
sessions = await loadSessions({ serviceUrl, ids });
|
||||
}
|
||||
|
||||
// complete flow if session and request id are provided
|
||||
if (requestId && sessionId) {
|
||||
if (requestId.startsWith("oidc_")) {
|
||||
// this finishes the login process for OIDC
|
||||
@@ -122,206 +123,251 @@ export async function GET(request: NextRequest) {
|
||||
request,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (requestId && requestId.startsWith("oidc_")) {
|
||||
const { authRequest } = await getAuthRequest({
|
||||
serviceUrl,
|
||||
authRequestId: requestId.replace("oidc_", ""),
|
||||
});
|
||||
// continue with OIDC
|
||||
if (requestId && requestId.startsWith("oidc_")) {
|
||||
const { authRequest } = await getAuthRequest({
|
||||
serviceUrl,
|
||||
authRequestId: requestId.replace("oidc_", ""),
|
||||
});
|
||||
|
||||
let organization = "";
|
||||
let suffix = "";
|
||||
let idpId = "";
|
||||
let organization = "";
|
||||
let suffix = "";
|
||||
let idpId = "";
|
||||
|
||||
if (authRequest?.scope) {
|
||||
const orgScope = authRequest.scope.find((s: string) =>
|
||||
ORG_SCOPE_REGEX.test(s),
|
||||
if (authRequest?.scope) {
|
||||
const orgScope = authRequest.scope.find((s: string) =>
|
||||
ORG_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
const idpScope = authRequest.scope.find((s: string) =>
|
||||
IDP_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
if (orgScope) {
|
||||
const matched = ORG_SCOPE_REGEX.exec(orgScope);
|
||||
organization = matched?.[1] ?? "";
|
||||
} else {
|
||||
const orgDomainScope = authRequest.scope.find((s: string) =>
|
||||
ORG_DOMAIN_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
const idpScope = authRequest.scope.find((s: string) =>
|
||||
IDP_SCOPE_REGEX.test(s),
|
||||
);
|
||||
if (orgDomainScope) {
|
||||
const matched = ORG_DOMAIN_SCOPE_REGEX.exec(orgDomainScope);
|
||||
const orgDomain = matched?.[1] ?? "";
|
||||
if (orgDomain) {
|
||||
const orgs = await getOrgsByDomain({
|
||||
serviceUrl,
|
||||
|
||||
if (orgScope) {
|
||||
const matched = ORG_SCOPE_REGEX.exec(orgScope);
|
||||
organization = matched?.[1] ?? "";
|
||||
} else {
|
||||
const orgDomainScope = authRequest.scope.find((s: string) =>
|
||||
ORG_DOMAIN_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
if (orgDomainScope) {
|
||||
const matched = ORG_DOMAIN_SCOPE_REGEX.exec(orgDomainScope);
|
||||
const orgDomain = matched?.[1] ?? "";
|
||||
if (orgDomain) {
|
||||
const orgs = await getOrgsByDomain({
|
||||
serviceUrl,
|
||||
|
||||
domain: orgDomain,
|
||||
});
|
||||
if (orgs.result && orgs.result.length === 1) {
|
||||
organization = orgs.result[0].id ?? "";
|
||||
suffix = orgDomain;
|
||||
}
|
||||
domain: orgDomain,
|
||||
});
|
||||
if (orgs.result && orgs.result.length === 1) {
|
||||
organization = orgs.result[0].id ?? "";
|
||||
suffix = orgDomain;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (idpScope) {
|
||||
const matched = IDP_SCOPE_REGEX.exec(idpScope);
|
||||
idpId = matched?.[1] ?? "";
|
||||
if (idpScope) {
|
||||
const matched = IDP_SCOPE_REGEX.exec(idpScope);
|
||||
idpId = matched?.[1] ?? "";
|
||||
|
||||
const identityProviders = await getActiveIdentityProviders({
|
||||
const identityProviders = await getActiveIdentityProviders({
|
||||
serviceUrl,
|
||||
orgId: organization ? organization : undefined,
|
||||
}).then((resp) => {
|
||||
return resp.identityProviders;
|
||||
});
|
||||
|
||||
const idp = identityProviders.find((idp) => idp.id === idpId);
|
||||
|
||||
if (idp) {
|
||||
const origin = request.nextUrl.origin;
|
||||
|
||||
const identityProviderType = identityProviders[0].type;
|
||||
let provider = idpTypeToSlug(identityProviderType);
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (requestId) {
|
||||
params.set("requestId", requestId);
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
}
|
||||
|
||||
return startIdentityProviderFlow({
|
||||
serviceUrl,
|
||||
orgId: organization ? organization : undefined,
|
||||
idpId,
|
||||
urls: {
|
||||
successUrl:
|
||||
`${origin}/idp/${provider}/success?` +
|
||||
new URLSearchParams(params),
|
||||
failureUrl:
|
||||
`${origin}/idp/${provider}/failure?` +
|
||||
new URLSearchParams(params),
|
||||
},
|
||||
}).then((resp) => {
|
||||
return resp.identityProviders;
|
||||
});
|
||||
|
||||
const idp = identityProviders.find((idp) => idp.id === idpId);
|
||||
|
||||
if (idp) {
|
||||
const origin = request.nextUrl.origin;
|
||||
|
||||
const identityProviderType = identityProviders[0].type;
|
||||
let provider = idpTypeToSlug(identityProviderType);
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (requestId) {
|
||||
params.set("requestId", requestId);
|
||||
if (
|
||||
resp.nextStep.value &&
|
||||
typeof resp.nextStep.value === "string"
|
||||
) {
|
||||
return NextResponse.redirect(resp.nextStep.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (authRequest && authRequest.prompt.includes(Prompt.CREATE)) {
|
||||
const registerUrl = new URL("/register", request.url);
|
||||
if (authRequest.id) {
|
||||
registerUrl.searchParams.set("requestId", `oidc_${authRequest.id}`);
|
||||
}
|
||||
if (organization) {
|
||||
registerUrl.searchParams.set("organization", organization);
|
||||
}
|
||||
|
||||
return NextResponse.redirect(registerUrl);
|
||||
}
|
||||
|
||||
// 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.prompt.includes(Prompt.SELECT_ACCOUNT)) {
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
} else if (authRequest.prompt.includes(Prompt.LOGIN)) {
|
||||
/**
|
||||
* The login prompt instructs the authentication server to prompt the user for re-authentication, regardless of whether the user is already authenticated
|
||||
*/
|
||||
|
||||
// if a hint is provided, skip loginname page and jump to the next page
|
||||
if (authRequest.loginHint) {
|
||||
try {
|
||||
let command: SendLoginnameCommand = {
|
||||
loginName: authRequest.loginHint,
|
||||
requestId: authRequest.id,
|
||||
};
|
||||
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
command = { ...command, organization };
|
||||
}
|
||||
|
||||
return startIdentityProviderFlow({
|
||||
serviceUrl,
|
||||
idpId,
|
||||
urls: {
|
||||
successUrl:
|
||||
`${origin}/idp/${provider}/success?` +
|
||||
new URLSearchParams(params),
|
||||
failureUrl:
|
||||
`${origin}/idp/${provider}/failure?` +
|
||||
new URLSearchParams(params),
|
||||
},
|
||||
}).then((resp) => {
|
||||
if (
|
||||
resp.nextStep.value &&
|
||||
typeof resp.nextStep.value === "string"
|
||||
) {
|
||||
return NextResponse.redirect(resp.nextStep.value);
|
||||
}
|
||||
});
|
||||
const res = await sendLoginname(command);
|
||||
|
||||
if (res && "redirect" in res && res?.redirect) {
|
||||
const absoluteUrl = new URL(res.redirect, request.url);
|
||||
return NextResponse.redirect(absoluteUrl.toString());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to execute sendLoginname:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (authRequest && authRequest.prompt.includes(Prompt.CREATE)) {
|
||||
const registerUrl = new URL("/register", request.url);
|
||||
const loginNameUrl = new URL("/loginname", request.url);
|
||||
if (authRequest.id) {
|
||||
registerUrl.searchParams.set("requestId", `oidc_${authRequest.id}`);
|
||||
loginNameUrl.searchParams.set("requestId", `oidc_${authRequest.id}`);
|
||||
}
|
||||
if (authRequest.loginHint) {
|
||||
loginNameUrl.searchParams.set("loginName", authRequest.loginHint);
|
||||
}
|
||||
if (organization) {
|
||||
registerUrl.searchParams.set("organization", organization);
|
||||
loginNameUrl.searchParams.set("organization", organization);
|
||||
}
|
||||
if (suffix) {
|
||||
loginNameUrl.searchParams.set("suffix", suffix);
|
||||
}
|
||||
return NextResponse.redirect(loginNameUrl);
|
||||
} else if (authRequest.prompt.includes(Prompt.NONE)) {
|
||||
/**
|
||||
* With an OIDC none prompt, the authentication server must not display any authentication or consent user interface pages.
|
||||
* This means that the user should not be prompted to enter their password again.
|
||||
* Instead, the server attempts to silently authenticate the user using an existing session or other authentication mechanisms that do not require user interaction
|
||||
**/
|
||||
const selectedSession = await findValidSession({
|
||||
serviceUrl,
|
||||
sessions,
|
||||
authRequest,
|
||||
});
|
||||
|
||||
if (!selectedSession || !selectedSession.id) {
|
||||
return NextResponse.json(
|
||||
{ error: "No active session found" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.redirect(registerUrl);
|
||||
}
|
||||
const cookie = sessionCookies.find(
|
||||
(cookie) => cookie.id === selectedSession.id,
|
||||
);
|
||||
|
||||
// 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.prompt.includes(Prompt.SELECT_ACCOUNT)) {
|
||||
if (!cookie || !cookie.id || !cookie.token) {
|
||||
return NextResponse.json(
|
||||
{ error: "No active session found" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const session = {
|
||||
sessionId: cookie.id,
|
||||
sessionToken: cookie.token,
|
||||
};
|
||||
|
||||
const { callbackUrl } = await createCallback({
|
||||
serviceUrl,
|
||||
req: create(CreateCallbackRequestSchema, {
|
||||
authRequestId: requestId.replace("oidc_", ""),
|
||||
callbackKind: {
|
||||
case: "session",
|
||||
value: create(SessionSchema, session),
|
||||
},
|
||||
}),
|
||||
});
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
// check for loginHint, userId hint and valid sessions
|
||||
let selectedSession = await findValidSession({
|
||||
serviceUrl,
|
||||
sessions,
|
||||
authRequest,
|
||||
});
|
||||
|
||||
if (!selectedSession || !selectedSession.id) {
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
} else if (authRequest.prompt.includes(Prompt.LOGIN)) {
|
||||
/**
|
||||
* The login prompt instructs the authentication server to prompt the user for re-authentication, regardless of whether the user is already authenticated
|
||||
*/
|
||||
}
|
||||
|
||||
// if a hint is provided, skip loginname page and jump to the next page
|
||||
if (authRequest.loginHint) {
|
||||
try {
|
||||
let command: SendLoginnameCommand = {
|
||||
loginName: authRequest.loginHint,
|
||||
requestId: authRequest.id,
|
||||
};
|
||||
const cookie = sessionCookies.find(
|
||||
(cookie) => cookie.id === selectedSession.id,
|
||||
);
|
||||
|
||||
if (organization) {
|
||||
command = { ...command, organization };
|
||||
}
|
||||
|
||||
const res = await sendLoginname(command);
|
||||
|
||||
if (res && "redirect" in res && res?.redirect) {
|
||||
const absoluteUrl = new URL(res.redirect, request.url);
|
||||
return NextResponse.redirect(absoluteUrl.toString());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to execute sendLoginname:", error);
|
||||
}
|
||||
}
|
||||
|
||||
const loginNameUrl = new URL("/loginname", request.url);
|
||||
if (authRequest.id) {
|
||||
loginNameUrl.searchParams.set(
|
||||
"requestId",
|
||||
`oidc_${authRequest.id}`,
|
||||
);
|
||||
}
|
||||
if (authRequest.loginHint) {
|
||||
loginNameUrl.searchParams.set("loginName", authRequest.loginHint);
|
||||
}
|
||||
if (organization) {
|
||||
loginNameUrl.searchParams.set("organization", organization);
|
||||
}
|
||||
if (suffix) {
|
||||
loginNameUrl.searchParams.set("suffix", suffix);
|
||||
}
|
||||
return NextResponse.redirect(loginNameUrl);
|
||||
} else if (authRequest.prompt.includes(Prompt.NONE)) {
|
||||
/**
|
||||
* With an OIDC none prompt, the authentication server must not display any authentication or consent user interface pages.
|
||||
* This means that the user should not be prompted to enter their password again.
|
||||
* Instead, the server attempts to silently authenticate the user using an existing session or other authentication mechanisms that do not require user interaction
|
||||
**/
|
||||
const selectedSession = await findValidSession({
|
||||
serviceUrl,
|
||||
sessions,
|
||||
authRequest,
|
||||
if (!cookie || !cookie.id || !cookie.token) {
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
}
|
||||
|
||||
if (!selectedSession || !selectedSession.id) {
|
||||
return NextResponse.json(
|
||||
{ error: "No active session found" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const cookie = sessionCookies.find(
|
||||
(cookie) => cookie.id === selectedSession.id,
|
||||
);
|
||||
|
||||
if (!cookie || !cookie.id || !cookie.token) {
|
||||
return NextResponse.json(
|
||||
{ error: "No active session found" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
|
||||
const session = {
|
||||
sessionId: cookie.id,
|
||||
sessionToken: cookie.token,
|
||||
};
|
||||
const session = {
|
||||
sessionId: cookie.id,
|
||||
sessionToken: cookie.token,
|
||||
};
|
||||
|
||||
try {
|
||||
const { callbackUrl } = await createCallback({
|
||||
serviceUrl,
|
||||
|
||||
req: create(CreateCallbackRequestSchema, {
|
||||
authRequestId: requestId.replace("oidc_", ""),
|
||||
callbackKind: {
|
||||
@@ -330,201 +376,155 @@ export async function GET(request: NextRequest) {
|
||||
},
|
||||
}),
|
||||
});
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
// check for loginHint, userId hint and valid sessions
|
||||
let selectedSession = await findValidSession({
|
||||
serviceUrl,
|
||||
sessions,
|
||||
authRequest,
|
||||
});
|
||||
|
||||
if (!selectedSession || !selectedSession.id) {
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
}
|
||||
|
||||
const cookie = sessionCookies.find(
|
||||
(cookie) => cookie.id === selectedSession.id,
|
||||
);
|
||||
|
||||
if (!cookie || !cookie.id || !cookie.token) {
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
}
|
||||
|
||||
const session = {
|
||||
sessionId: cookie.id,
|
||||
sessionToken: cookie.token,
|
||||
};
|
||||
|
||||
try {
|
||||
const { callbackUrl } = await createCallback({
|
||||
serviceUrl,
|
||||
|
||||
req: create(CreateCallbackRequestSchema, {
|
||||
authRequestId: requestId.replace("oidc_", ""),
|
||||
callbackKind: {
|
||||
case: "session",
|
||||
value: create(SessionSchema, session),
|
||||
},
|
||||
}),
|
||||
});
|
||||
if (callbackUrl) {
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
console.log(
|
||||
"could not create callback, redirect user to choose other account",
|
||||
);
|
||||
return gotoAccounts({
|
||||
request,
|
||||
organization,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const loginNameUrl = new URL("/loginname", request.url);
|
||||
|
||||
loginNameUrl.searchParams.set("requestId", requestId);
|
||||
if (authRequest?.loginHint) {
|
||||
loginNameUrl.searchParams.set("loginName", authRequest.loginHint);
|
||||
loginNameUrl.searchParams.set("submit", "true"); // autosubmit
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
loginNameUrl.searchParams.append("organization", organization);
|
||||
// loginNameUrl.searchParams.set("organization", organization);
|
||||
}
|
||||
|
||||
return NextResponse.redirect(loginNameUrl);
|
||||
}
|
||||
} else if (requestId && requestId.startsWith("saml_")) {
|
||||
// handle saml request
|
||||
const { samlRequest } = await getSAMLRequest({
|
||||
serviceUrl,
|
||||
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",
|
||||
});
|
||||
if (callbackUrl) {
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{ error: "Failed to complete SAML request" },
|
||||
{ status: response.status },
|
||||
console.log(
|
||||
"could not create callback, redirect user to choose other account",
|
||||
);
|
||||
return gotoAccounts({
|
||||
request,
|
||||
organization,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
"could not create response, redirect user to choose other account",
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `saml_${samlRequest.id}`,
|
||||
requestId: `oidc_${authRequest.id}`,
|
||||
organization,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
} else {
|
||||
const loginNameUrl = new URL("/loginname", request.url);
|
||||
|
||||
loginNameUrl.searchParams.set("requestId", requestId);
|
||||
if (authRequest?.loginHint) {
|
||||
loginNameUrl.searchParams.set("loginName", authRequest.loginHint);
|
||||
loginNameUrl.searchParams.set("submit", "true"); // autosubmit
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
loginNameUrl.searchParams.append("organization", organization);
|
||||
// loginNameUrl.searchParams.set("organization", organization);
|
||||
}
|
||||
|
||||
return NextResponse.redirect(loginNameUrl);
|
||||
}
|
||||
}
|
||||
// continue with SAML
|
||||
else if (requestId && requestId.startsWith("saml_")) {
|
||||
const { samlRequest } = await getSAMLRequest({
|
||||
serviceUrl,
|
||||
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}`,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{ error: "No authRequest nor samlRequest provided" },
|
||||
{ status: 500 },
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return gotoAccounts({
|
||||
request,
|
||||
requestId: `saml_${samlRequest.id}`,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{ error: "No authRequest nor samlRequest provided" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user