diff --git a/apps/login/app/(login)/register/idp/[provider]/success/page.tsx b/apps/login/app/(login)/idp/[provider]/success/page.tsx
similarity index 71%
rename from apps/login/app/(login)/register/idp/[provider]/success/page.tsx
rename to apps/login/app/(login)/idp/[provider]/success/page.tsx
index f7b55fcffe5..3779054fbec 100644
--- a/apps/login/app/(login)/register/idp/[provider]/success/page.tsx
+++ b/apps/login/app/(login)/idp/[provider]/success/page.tsx
@@ -1,6 +1,7 @@
import { ProviderSlug } from "#/lib/demos";
import { server } from "#/lib/zitadel";
import Alert, { AlertType } from "#/ui/Alert";
+import { createSessionForIdpAndUpdateCookie } from "#/utils/session";
import {
AddHumanUserRequest,
IDPInformation,
@@ -96,21 +97,50 @@ export default async function Page({
return retrieveIDP(id, token)
.then((information) => {
if (information) {
- return createUser(provider, information).catch((error) => {
- throw new Error(error.details);
- });
+ console.log(information);
+
+ // handle login
+ if (information.userId) {
+ return createSessionForIdpAndUpdateCookie(
+ information.userId,
+ {
+ idpIntentId: id,
+ idpIntentToken: token,
+ },
+ undefined
+ )
+ .then((session) => {
+ return (
+
+
Login successful
+
You have successfully been loggedIn!
+
+ );
+ })
+ .catch((error) => {
+ throw new Error(error.details);
+ });
+ } else {
+ // handle register
+
+ return createUser(provider, information)
+ .then((userId) => {
+ return (
+
+
Register successful
+
You have successfully been registered!
+
+ );
+ })
+ .catch((error) => {
+ throw new Error(error.details);
+ });
+ }
} else {
throw new Error("Could not get user information.");
}
})
- .then((userId) => {
- return (
-
-
Register successful
-
You have successfully been registered!
-
- );
- })
+
.catch((error: Error) => {
return (
diff --git a/apps/login/app/(login)/register/idp/page.tsx b/apps/login/app/(login)/idp/page.tsx
similarity index 100%
rename from apps/login/app/(login)/register/idp/page.tsx
rename to apps/login/app/(login)/idp/page.tsx
diff --git a/apps/login/app/(login)/loginname/page.tsx b/apps/login/app/(login)/loginname/page.tsx
index 98ae5535681..3a80fc3b7c9 100644
--- a/apps/login/app/(login)/loginname/page.tsx
+++ b/apps/login/app/(login)/loginname/page.tsx
@@ -1,5 +1,31 @@
-import { getLoginSettings, server } from "#/lib/zitadel";
+import {
+ getLegalAndSupportSettings,
+ getLoginSettings,
+ server,
+} from "#/lib/zitadel";
+import { SignInWithIDP } from "#/ui/SignInWithIDP";
import UsernameForm from "#/ui/UsernameForm";
+import {
+ GetActiveIdentityProvidersResponse,
+ IdentityProvider,
+ ZitadelServer,
+ settings,
+} from "@zitadel/server";
+
+function getIdentityProviders(
+ server: ZitadelServer,
+ orgId?: string
+): Promise
{
+ const settingsService = settings.getSettings(server);
+ return settingsService
+ .getActiveIdentityProviders(
+ orgId ? { ctx: { orgId } } : { ctx: { instance: true } },
+ {}
+ )
+ .then((resp: GetActiveIdentityProvidersResponse) => {
+ return resp.identityProviders;
+ });
+}
export default async function Page({
searchParams,
@@ -12,6 +38,14 @@ export default async function Page({
const submit: boolean = searchParams?.submit === "true";
const loginSettings = await getLoginSettings(server, organization);
+ const legal = await getLegalAndSupportSettings(server);
+
+ // TODO if org idps should be shown replace emptystring with the orgId.
+ const identityProviders = await getIdentityProviders(server, "");
+
+ const host = process.env.VERCEL_URL
+ ? `https://${process.env.VERCEL_URL}`
+ : "http://localhost:3000";
return (
@@ -25,6 +59,13 @@ export default async function Page({
organization={organization}
submit={submit}
/>
+
+ {legal && identityProviders && process.env.ZITADEL_API_URL && (
+
+ )}
);
}
diff --git a/apps/login/app/(login)/login/route.ts b/apps/login/app/login/route.ts
similarity index 100%
rename from apps/login/app/(login)/login/route.ts
rename to apps/login/app/login/route.ts
diff --git a/apps/login/lib/zitadel.ts b/apps/login/lib/zitadel.ts
index e075a43a80b..4fcea77c020 100644
--- a/apps/login/lib/zitadel.ts
+++ b/apps/login/lib/zitadel.ts
@@ -125,6 +125,23 @@ export async function createSession(
);
}
+export async function createSessionForUserIdAndIdpIntent(
+ server: ZitadelServer,
+ userId: string,
+ idpIntent: {
+ idpIntentId?: string | undefined;
+ idpIntentToken?: string | undefined;
+ }
+): Promise {
+ const sessionService = session.getSession(server);
+ return sessionService.createSession(
+ {
+ checks: { user: { userId }, idpIntent },
+ },
+ {}
+ );
+}
+
export async function setSession(
server: ZitadelServer,
sessionId: string,
diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx
index f8f343124b9..f37be1196b7 100644
--- a/apps/login/ui/SessionItem.tsx
+++ b/apps/login/ui/SessionItem.tsx
@@ -42,8 +42,12 @@ export default function SessionItem({
const validPassword = session?.factors?.password?.verifiedAt;
const validPasskey = session?.factors?.webAuthN?.verifiedAt;
+ const stillValid = session.expirationDate
+ ? session.expirationDate > new Date()
+ : true;
- const validUser = validPassword || validPasskey;
+ const validDate = validPassword || validPasskey;
+ const validUser = (validPassword || validPasskey) && stillValid;
return (
{validUser && (
- {moment(new Date(validUser)).fromNow()}
+ {validDate && moment(new Date(validDate)).fromNow()}
)}
diff --git a/apps/login/ui/SignInWithIDP.tsx b/apps/login/ui/SignInWithIDP.tsx
index a7788415940..628c4818913 100644
--- a/apps/login/ui/SignInWithIDP.tsx
+++ b/apps/login/ui/SignInWithIDP.tsx
@@ -40,8 +40,8 @@ export function SignInWithIDP({
},
body: JSON.stringify({
idpId,
- successUrl: `${host}/register/idp/${provider}/success`,
- failureUrl: `${host}/register/idp/${provider}/failure`,
+ successUrl: `${host}/idp/${provider}/success`,
+ failureUrl: `${host}/idp/${provider}/failure`,
}),
});
diff --git a/apps/login/utils/session.ts b/apps/login/utils/session.ts
index d40fc8ec55b..99aad8abc49 100644
--- a/apps/login/utils/session.ts
+++ b/apps/login/utils/session.ts
@@ -1,4 +1,10 @@
-import { createSession, getSession, server, setSession } from "#/lib/zitadel";
+import {
+ createSession,
+ createSessionForUserIdAndIdpIntent,
+ getSession,
+ server,
+ setSession,
+} from "#/lib/zitadel";
import {
SessionCookie,
addSessionToCookie,
@@ -49,6 +55,50 @@ export async function createSessionAndUpdateCookie(
}
}
+export async function createSessionForIdpAndUpdateCookie(
+ userId: string,
+ idpIntent: {
+ idpIntentId?: string | undefined;
+ idpIntentToken?: string | undefined;
+ },
+ authRequestId: string | undefined
+): Promise {
+ const createdSession = await createSessionForUserIdAndIdpIntent(
+ server,
+ userId,
+ idpIntent
+ );
+
+ if (createdSession) {
+ return getSession(
+ server,
+ createdSession.sessionId,
+ createdSession.sessionToken
+ ).then((response) => {
+ if (response?.session && response.session?.factors?.user?.loginName) {
+ const sessionCookie: SessionCookie = {
+ id: createdSession.sessionId,
+ token: createdSession.sessionToken,
+ changeDate: response.session.changeDate?.toString() ?? "",
+ loginName: response.session?.factors?.user?.loginName ?? "",
+ };
+
+ if (authRequestId) {
+ sessionCookie.authRequestId = authRequestId;
+ }
+
+ return addSessionToCookie(sessionCookie).then(() => {
+ return response.session as Session;
+ });
+ } else {
+ throw "could not get session or session does not have loginName";
+ }
+ });
+ } else {
+ throw "Could not create session";
+ }
+}
+
export type SessionWithChallenges = Session & {
challenges: Challenges | undefined;
};