mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 15:27:33 +00:00
dc
This commit is contained in:
@@ -197,6 +197,11 @@
|
|||||||
"title": "would like to connect:",
|
"title": "would like to connect:",
|
||||||
"description": "By clicking Allow, you allow this app and Zitadel to use your information in accordance with their respective terms of service and privacy policies. You can revoke this access at any time.",
|
"description": "By clicking Allow, you allow this app and Zitadel to use your information in accordance with their respective terms of service and privacy policies. You can revoke this access at any time.",
|
||||||
"submit": "Allow"
|
"submit": "Allow"
|
||||||
|
},
|
||||||
|
"scope": {
|
||||||
|
"email": "Access your email address.",
|
||||||
|
"profile": "Access your full profile information.",
|
||||||
|
"offline_access": "Allow offline access to your account."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
@@ -33,6 +33,8 @@ export default async function Page(props: {
|
|||||||
userCode,
|
userCode,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(deviceAuthorizationRequest);
|
||||||
|
|
||||||
let defaultOrganization;
|
let defaultOrganization;
|
||||||
if (!organization) {
|
if (!organization) {
|
||||||
const org: Organization | null = await getDefaultOrg({
|
const org: Organization | null = await getDefaultOrg({
|
||||||
@@ -48,19 +50,28 @@ export default async function Page(props: {
|
|||||||
organization: organization ?? defaultOrganization,
|
organization: organization ?? defaultOrganization,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
|
||||||
|
if (requestId) {
|
||||||
|
params.append("requestId", requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (organization) {
|
||||||
|
params.append("organization", organization);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme
|
<DynamicTheme
|
||||||
branding={branding}
|
branding={branding}
|
||||||
appName={deviceAuthorizationRequest?.appName}
|
appName={deviceAuthorizationRequest?.appName}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
{!userCode && (
|
<h1>{t("usercode.title")}</h1>
|
||||||
<>
|
<p className="ztdl-p">{t("usercode.description")}</p>
|
||||||
<h1>{t("usercode.title")}</h1>
|
<ConsentScreen
|
||||||
<p className="ztdl-p">{t("usercode.description")}</p>
|
scope={deviceAuthorizationRequest?.scope}
|
||||||
<ConsentScreen scope={deviceAuthorizationRequest?.scope} />
|
nextUrl={`/loginname?` + params}
|
||||||
</>
|
/>
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
);
|
);
|
||||||
|
@@ -9,7 +9,6 @@ import {
|
|||||||
createCallback,
|
createCallback,
|
||||||
createResponse,
|
createResponse,
|
||||||
getBrandingSettings,
|
getBrandingSettings,
|
||||||
getDeviceAuthorizationRequest,
|
|
||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
getSession,
|
getSession,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
@@ -64,24 +63,17 @@ async function loadSession(
|
|||||||
return redirect(url);
|
return redirect(url);
|
||||||
});
|
});
|
||||||
} else if (requestId && requestId.startsWith("device_")) {
|
} else if (requestId && requestId.startsWith("device_")) {
|
||||||
const userCode = requestId.replace("device_", "");
|
const session = {
|
||||||
|
sessionId: recent.id,
|
||||||
const { deviceAuthorizationRequest } = await getDeviceAuthorizationRequest({
|
sessionToken: recent.token,
|
||||||
serviceUrl,
|
};
|
||||||
userCode,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!deviceAuthorizationRequest) {
|
|
||||||
throw new Error("Device authorization request not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
return authorizeOrDenyDeviceAuthorization({
|
return authorizeOrDenyDeviceAuthorization({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
deviceAuthorizationId: deviceAuthorizationRequest?.id,
|
deviceAuthorizationId: requestId.replace("device_", ""),
|
||||||
session: {
|
session,
|
||||||
sessionId: recent.id,
|
}).then(() => {
|
||||||
sessionToken: recent.token,
|
return session;
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +97,11 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
|
|
||||||
const { loginName, requestId, organization } = searchParams;
|
const { loginName, requestId, organization } = searchParams;
|
||||||
const sessionFactors = await loadSession(serviceUrl, loginName, requestId);
|
// const sessionFactors = await loadSession(serviceUrl, loginName, requestId);
|
||||||
|
|
||||||
|
const sessionFactors = sessionId
|
||||||
|
? await loadSessionById(serviceUrl, sessionId, organization)
|
||||||
|
: await loadSessionByLoginname(serviceUrl, loginName, organization);
|
||||||
|
|
||||||
const branding = await getBrandingSettings({
|
const branding = await getBrandingSettings({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
|
@@ -1,11 +1,57 @@
|
|||||||
export function ConsentScreen({ scope }: { scope?: string[] }) {
|
import { useTranslations } from "next-intl";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { Button, ButtonVariants } from "./button";
|
||||||
|
|
||||||
|
export function ConsentScreen({
|
||||||
|
scope,
|
||||||
|
nextUrl,
|
||||||
|
}: {
|
||||||
|
scope?: string[];
|
||||||
|
nextUrl: string;
|
||||||
|
}) {
|
||||||
|
const t = useTranslations();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="w-full flex flex-col items-center space-y-4">
|
||||||
<h1>Consent</h1>
|
<ul className="list-disc space-y-2 w-full">
|
||||||
<p className="ztdl-p">Please confirm your consent.</p>
|
{scope?.map((s) => {
|
||||||
<div className="flex flex-col items-center space-y-4">
|
const translationKey = `device.scope.${s}`;
|
||||||
<button className="btn btn-primary">Accept</button>
|
const description = t(translationKey, null);
|
||||||
<button className="btn btn-secondary">Reject</button>
|
|
||||||
|
// Check if the key itself is returned and provide a fallback
|
||||||
|
const resolvedDescription =
|
||||||
|
description === translationKey
|
||||||
|
? "No description available."
|
||||||
|
: description;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<li
|
||||||
|
key={s}
|
||||||
|
className="grid grid-cols-4 w-full text-sm flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light py-2 px-4 rounded-md transition-all"
|
||||||
|
>
|
||||||
|
<strong className="col-span-1">{s}</strong>
|
||||||
|
<span className="col-span-3">{resolvedDescription}</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="mt-4 flex w-full flex-row items-center">
|
||||||
|
<Button variant={ButtonVariants.Destructive} data-testid="deny-button">
|
||||||
|
Deny
|
||||||
|
</Button>
|
||||||
|
<span className="flex-grow"></span>
|
||||||
|
|
||||||
|
<Link href={nextUrl}>
|
||||||
|
<Button
|
||||||
|
data-testid="submit-button"
|
||||||
|
type="submit"
|
||||||
|
className="self-end"
|
||||||
|
variant={ButtonVariants.Primary}
|
||||||
|
>
|
||||||
|
continue
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@@ -51,7 +51,7 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
|||||||
return router.push(
|
return router.push(
|
||||||
`/device/consent?` +
|
`/device/consent?` +
|
||||||
new URLSearchParams({
|
new URLSearchParams({
|
||||||
requestId: `device_${userCode}`,
|
requestId: `device_${response.deviceAuthorizationRequest.id}`,
|
||||||
user_code: value.userCode,
|
user_code: value.userCode,
|
||||||
}).toString(),
|
}).toString(),
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user