mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-13 10:57:32 +00:00
move flow completion to signedin page
This commit is contained in:
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "Willkommen {user}!",
|
"title": "Willkommen {user}!",
|
||||||
"description": "Sie sind angemeldet.",
|
"description": "Sie sind angemeldet.",
|
||||||
"continue": "Weiter"
|
"continue": "Weiter",
|
||||||
|
"error": {
|
||||||
|
"title": "Fehler",
|
||||||
|
"description": "Ein Fehler ist aufgetreten."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "Keine Benutzer-ID angegeben!",
|
"userIdMissing": "Keine Benutzer-ID angegeben!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "Welcome {user}!",
|
"title": "Welcome {user}!",
|
||||||
"description": "You are signed in.",
|
"description": "You are signed in.",
|
||||||
"continue": "Continue"
|
"continue": "Continue",
|
||||||
|
"error": {
|
||||||
|
"title": "Error",
|
||||||
|
"description": "An error occurred while trying to sign in."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "No userId provided!",
|
"userIdMissing": "No userId provided!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "¡Bienvenido {user}!",
|
"title": "¡Bienvenido {user}!",
|
||||||
"description": "Has iniciado sesión.",
|
"description": "Has iniciado sesión.",
|
||||||
"continue": "Continuar"
|
"continue": "Continuar",
|
||||||
|
"error": {
|
||||||
|
"title": "Error",
|
||||||
|
"description": "Ocurrió un error al iniciar sesión."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "¡No se proporcionó userId!",
|
"userIdMissing": "¡No se proporcionó userId!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "Benvenuto {user}!",
|
"title": "Benvenuto {user}!",
|
||||||
"description": "Sei connesso.",
|
"description": "Sei connesso.",
|
||||||
"continue": "Continua"
|
"continue": "Continua",
|
||||||
|
"error": {
|
||||||
|
"title": "Errore",
|
||||||
|
"description": "Si è verificato un errore durante il tentativo di accesso."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "Nessun userId fornito!",
|
"userIdMissing": "Nessun userId fornito!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "Witaj {user}!",
|
"title": "Witaj {user}!",
|
||||||
"description": "Jesteś zalogowany.",
|
"description": "Jesteś zalogowany.",
|
||||||
"continue": "Kontynuuj"
|
"continue": "Kontynuuj",
|
||||||
|
"error": {
|
||||||
|
"title": "Błąd",
|
||||||
|
"description": "Nie można załadować danych. Sprawdź połączenie z internetem lub spróbuj ponownie później."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "Nie podano identyfikatora użytkownika!",
|
"userIdMissing": "Nie podano identyfikatora użytkownika!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "Добро пожаловать, {user}!",
|
"title": "Добро пожаловать, {user}!",
|
||||||
"description": "Вы вошли в систему.",
|
"description": "Вы вошли в систему.",
|
||||||
"continue": "Продолжить"
|
"continue": "Продолжить",
|
||||||
|
"error": {
|
||||||
|
"title": "Ошибка",
|
||||||
|
"description": "Не удалось войти в систему. Проверьте свои данные и попробуйте снова."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "Не указан userId!",
|
"userIdMissing": "Не указан userId!",
|
||||||
|
@@ -166,7 +166,11 @@
|
|||||||
"signedin": {
|
"signedin": {
|
||||||
"title": "欢迎 {user}!",
|
"title": "欢迎 {user}!",
|
||||||
"description": "您已登录。",
|
"description": "您已登录。",
|
||||||
"continue": "继续"
|
"continue": "继续",
|
||||||
|
"error": {
|
||||||
|
"title": "错误",
|
||||||
|
"description": "登录时发生错误。"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"verify": {
|
"verify": {
|
||||||
"userIdMissing": "未提供用户 ID!",
|
"userIdMissing": "未提供用户 ID!",
|
||||||
|
@@ -2,7 +2,11 @@ import { Alert, AlertType } from "@/components/alert";
|
|||||||
import { Button, ButtonVariants } from "@/components/button";
|
import { Button, ButtonVariants } from "@/components/button";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import {
|
||||||
|
getMostRecentCookieWithLoginname,
|
||||||
|
getSessionCookieById,
|
||||||
|
} from "@/lib/cookies";
|
||||||
|
import { completeDeviceAuthorization } from "@/lib/server/device";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service";
|
import { getServiceUrlFromHeaders } from "@/lib/service";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import {
|
import {
|
||||||
@@ -41,6 +45,36 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
|
|
||||||
const { loginName, requestId, organization, sessionId } = searchParams;
|
const { loginName, requestId, organization, sessionId } = searchParams;
|
||||||
|
|
||||||
|
const branding = await getBrandingSettings({
|
||||||
|
serviceUrl,
|
||||||
|
organization,
|
||||||
|
});
|
||||||
|
|
||||||
|
// complete device authorization flow if device requestId is present
|
||||||
|
if (requestId && requestId.startsWith("device_")) {
|
||||||
|
const cookie = sessionId
|
||||||
|
? await getSessionCookieById({ sessionId, organization })
|
||||||
|
: await getMostRecentCookieWithLoginname({
|
||||||
|
loginName: loginName,
|
||||||
|
organization: organization,
|
||||||
|
});
|
||||||
|
|
||||||
|
await completeDeviceAuthorization(requestId.replace("device_", ""), {
|
||||||
|
sessionId: cookie.id,
|
||||||
|
sessionToken: cookie.token,
|
||||||
|
}).catch((err) => {
|
||||||
|
return (
|
||||||
|
<DynamicTheme branding={branding}>
|
||||||
|
<div className="flex flex-col items-center space-y-4">
|
||||||
|
<h1>{t("error.title")}</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">{t("error.description")}</p>
|
||||||
|
<Alert>{err.message}</Alert>
|
||||||
|
</div>
|
||||||
|
</DynamicTheme>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const sessionFactors = sessionId
|
const sessionFactors = sessionId
|
||||||
? await loadSessionById(serviceUrl, sessionId, organization)
|
? await loadSessionById(serviceUrl, sessionId, organization)
|
||||||
: await loadMostRecentSession({
|
: await loadMostRecentSession({
|
||||||
@@ -48,11 +82,6 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
sessionParams: { loginName, organization },
|
sessionParams: { loginName, organization },
|
||||||
});
|
});
|
||||||
|
|
||||||
const branding = await getBrandingSettings({
|
|
||||||
serviceUrl,
|
|
||||||
organization,
|
|
||||||
});
|
|
||||||
|
|
||||||
let loginSettings;
|
let loginSettings;
|
||||||
if (!requestId) {
|
if (!requestId) {
|
||||||
loginSettings = await getLoginSettings({
|
loginSettings = await getLoginSettings({
|
||||||
@@ -69,6 +98,13 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
</h1>
|
</h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("description")}</p>
|
<p className="ztdl-p mb-6 block">{t("description")}</p>
|
||||||
|
|
||||||
|
<UserAvatar
|
||||||
|
loginName={loginName ?? sessionFactors?.factors?.user?.loginName}
|
||||||
|
displayName={sessionFactors?.factors?.user?.displayName}
|
||||||
|
showDropdown={!(requestId && requestId.startsWith("device_"))}
|
||||||
|
searchParams={searchParams}
|
||||||
|
/>
|
||||||
|
|
||||||
{requestId && requestId.startsWith("device_") && (
|
{requestId && requestId.startsWith("device_") && (
|
||||||
<Alert type={AlertType.INFO}>
|
<Alert type={AlertType.INFO}>
|
||||||
You can now close this window and return to the device where you
|
You can now close this window and return to the device where you
|
||||||
@@ -76,13 +112,6 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<UserAvatar
|
|
||||||
loginName={loginName ?? sessionFactors?.factors?.user?.loginName}
|
|
||||||
displayName={sessionFactors?.factors?.user?.displayName}
|
|
||||||
showDropdown
|
|
||||||
searchParams={searchParams}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* {sessionFactors?.id && (
|
{/* {sessionFactors?.id && (
|
||||||
<SelfServiceMenu sessionId={sessionFactors?.id} />
|
<SelfServiceMenu sessionId={sessionFactors?.id} />
|
||||||
)} */}
|
)} */}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { denyDeviceAuthorization } from "@/lib/server/oidc";
|
import { completeDeviceAuthorization } from "@/lib/server/device";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
@@ -27,7 +27,9 @@ export function ConsentScreen({
|
|||||||
|
|
||||||
async function denyDeviceAuth() {
|
async function denyDeviceAuth() {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await denyDeviceAuthorization(deviceAuthorizationRequestId)
|
const response = await completeDeviceAuthorization(
|
||||||
|
deviceAuthorizationRequestId,
|
||||||
|
)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setError("Could not register user");
|
setError("Could not register user");
|
||||||
return;
|
return;
|
||||||
|
@@ -36,7 +36,7 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
|||||||
|
|
||||||
const response = await getDeviceAuthorizationRequest(value.userCode)
|
const response = await getDeviceAuthorizationRequest(value.userCode)
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setError("Could not complete the request");
|
setError("Could not continue the request");
|
||||||
return;
|
return;
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -44,7 +44,7 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response || !response.deviceAuthorizationRequest?.id) {
|
if (!response || !response.deviceAuthorizationRequest?.id) {
|
||||||
setError("Could not complete the request");
|
setError("Could not continue the request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
apps/login/src/lib/server/device.ts
Normal file
20
apps/login/src/lib/server/device.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import { authorizeOrDenyDeviceAuthorization } from "@/lib/zitadel";
|
||||||
|
import { headers } from "next/headers";
|
||||||
|
import { getServiceUrlFromHeaders } from "../service";
|
||||||
|
|
||||||
|
export async function completeDeviceAuthorization(
|
||||||
|
deviceAuthorizationId: string,
|
||||||
|
session?: { sessionId: string; sessionToken: string },
|
||||||
|
) {
|
||||||
|
const _headers = await headers();
|
||||||
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
|
|
||||||
|
// without the session, device auth request is denied
|
||||||
|
return authorizeOrDenyDeviceAuthorization({
|
||||||
|
serviceUrl,
|
||||||
|
deviceAuthorizationId,
|
||||||
|
session,
|
||||||
|
});
|
||||||
|
}
|
@@ -1,9 +1,6 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
import {
|
import { getDeviceAuthorizationRequest as zitadelGetDeviceAuthorizationRequest } from "@/lib/zitadel";
|
||||||
authorizeOrDenyDeviceAuthorization,
|
|
||||||
getDeviceAuthorizationRequest as zitadelGetDeviceAuthorizationRequest,
|
|
||||||
} from "@/lib/zitadel";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { getServiceUrlFromHeaders } from "../service";
|
import { getServiceUrlFromHeaders } from "../service";
|
||||||
|
|
||||||
@@ -16,14 +13,3 @@ export async function getDeviceAuthorizationRequest(userCode: string) {
|
|||||||
userCode,
|
userCode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function denyDeviceAuthorization(deviceAuthorizationId: string) {
|
|
||||||
const _headers = await headers();
|
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
|
||||||
|
|
||||||
// without the session, device auth request is denied
|
|
||||||
return authorizeOrDenyDeviceAuthorization({
|
|
||||||
serviceUrl,
|
|
||||||
deviceAuthorizationId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
@@ -952,6 +952,10 @@ export async function authorizeOrDenyDeviceAuthorization({
|
|||||||
deviceAuthorizationId: string;
|
deviceAuthorizationId: string;
|
||||||
session?: { sessionId: string; sessionToken: string };
|
session?: { sessionId: string; sessionToken: string };
|
||||||
}) {
|
}) {
|
||||||
|
console.log("authorizeOrDenyDeviceAuthorization");
|
||||||
|
|
||||||
|
console.log("session", session);
|
||||||
|
|
||||||
const oidcService = await createServiceForHost(OIDCService, serviceUrl);
|
const oidcService = await createServiceForHost(OIDCService, serviceUrl);
|
||||||
|
|
||||||
return oidcService.authorizeOrDenyDeviceAuthorization({
|
return oidcService.authorizeOrDenyDeviceAuthorization({
|
||||||
|
Reference in New Issue
Block a user