createpasskeyregistrationlink

This commit is contained in:
Max Peintner
2023-06-12 10:38:28 +02:00
parent 717c46bc46
commit 084051889b
6 changed files with 93 additions and 39 deletions

View File

@@ -1,9 +1,8 @@
import { getSession, server } from "#/lib/zitadel"; import { getSession, server } from "#/lib/zitadel";
import Alert from "#/ui/Alert"; import Alert, { AlertType } from "#/ui/Alert";
import RegisterPasskey from "#/ui/RegisterPasskey"; import RegisterPasskey from "#/ui/RegisterPasskey";
import UserAvatar from "#/ui/UserAvatar"; import UserAvatar from "#/ui/UserAvatar";
import { getMostRecentCookieWithLoginname } from "#/utils/cookies"; import { getMostRecentCookieWithLoginname } from "#/utils/cookies";
import { useRouter } from "next/navigation";
export default async function Page({ export default async function Page({
searchParams, searchParams,
@@ -15,7 +14,6 @@ export default async function Page({
async function loadSession(loginName?: string) { async function loadSession(loginName?: string) {
const recent = await getMostRecentCookieWithLoginname(loginName); const recent = await getMostRecentCookieWithLoginname(loginName);
return getSession(server, recent.id, recent.token).then((response) => { return getSession(server, recent.id, recent.token).then((response) => {
if (response?.session) { if (response?.session) {
return response.session; return response.session;
@@ -27,7 +25,14 @@ export default async function Page({
return ( return (
<div className="flex flex-col items-center space-y-4"> <div className="flex flex-col items-center space-y-4">
<h1>Register Passkey</h1> <h1>Register Passkey</h1>
<p className="ztdl-p mb-6 block">Setup your device for passkeys.</p> <p className="ztdl-p mb-6 block">
Setup your user to authenticate with passkeys.
</p>
<Alert type={AlertType.INFO}>
A passkey is an authentication method on a device like your fingerprint,
Apple FaceID or similar.
</Alert>
{!sessionFactors && ( {!sessionFactors && (
<div className="py-4"> <div className="py-4">

View File

@@ -94,6 +94,8 @@ export async function PUT(request: NextRequest) {
loginName: session.factors?.user?.loginName ?? "", loginName: session.factors?.user?.loginName ?? "",
}; };
console.log("new token", recent.token, newCookie.token);
return updateSessionCookie(sessionCookie.id, newCookie) return updateSessionCookie(sessionCookie.id, newCookie)
.then(() => { .then(() => {
return NextResponse.json({ factors: session.factors }); return NextResponse.json({ factors: session.factors });

View File

@@ -22,6 +22,7 @@ import {
DeleteSessionResponse, DeleteSessionResponse,
VerifyPasskeyRegistrationResponse, VerifyPasskeyRegistrationResponse,
} from "@zitadel/server"; } from "@zitadel/server";
import { Metadata } from "nice-grpc";
export const zitadelConfig: ZitadelServerOptions = { export const zitadelConfig: ZitadelServerOptions = {
name: "zitadel login", name: "zitadel login",
@@ -185,24 +186,8 @@ export async function setEmail(
); );
} }
/** const bearerTokenMetadata = (token: string) =>
* new Metadata({ authorization: `Bearer ${token}` });
* @param server
* @param userId the id of the user where the email should be set
* @returns the newly set email
*/
export async function registerPasskey(
server: ZitadelServer,
userId: string
): Promise<any> {
const userservice = user.getUser(server);
return userservice.registerPasskey(
{
userId,
},
{}
);
}
/** /**
* *
@@ -214,22 +199,22 @@ export async function createPasskeyRegistrationLink(
userId: string, userId: string,
sessionToken: string sessionToken: string
): Promise<any> { ): Promise<any> {
// this actions will be made from the currently seleected user // this actions will be made from the currently seleected user
const zitadelConfig: ZitadelServerOptions = { // const zitadelConfig: ZitadelServerOptions = {
name: "zitadel login", // name: "zitadel login",
apiUrl: process.env.ZITADEL_API_URL ?? "", // apiUrl: process.env.ZITADEL_API_URL ?? "",
token: `${sessionToken}`, // token: "",
}; // };
const server: ZitadelServer = initializeServer(zitadelConfig);
// const authserver: ZitadelServer = initializeServer(zitadelConfig);
// console.log("server", authserver);
const userservice = user.getUser(server); const userservice = user.getUser(server);
return userservice.createPasskeyRegistrationLink( return userservice.createPasskeyRegistrationLink(
{ {
userId, userId,
// returnCode: new ReturnPasskeyRegistrationCode(), returnCode: {},
}, }
{} // { metadata: bearerTokenMetadata(sessionToken) }
); );
} }
@@ -257,4 +242,34 @@ export async function verifyPasskeyRegistration(
{} {}
); );
} }
/**
*
* @param server
* @param userId the id of the user where the email should be set
* @returns the newly set email
*/
export async function registerPasskey(
userId: string,
sessionToken: string
): Promise<any> {
// this actions will be made from the currently seleected user
const zitadelConfig: ZitadelServerOptions = {
name: "zitadel login",
apiUrl: process.env.ZITADEL_API_URL ?? "",
token: "",
};
const authserver: ZitadelServer = initializeServer(zitadelConfig);
console.log("server", authserver);
const userservice = user.getUser(server);
return userservice.registerPasskey(
{
userId,
// returnCode: new ReturnPasskeyRegistrationCode(),
},
{ metadata: bearerTokenMetadata(sessionToken) }
);
}
export { server }; export { server };

View File

@@ -1,12 +1,34 @@
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
import clsx from "clsx";
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;
type?: AlertType;
}; };
export default function Alert({ children }: Props) { export enum AlertType {
ALERT,
INFO,
}
const yellow =
"border-yellow-600/40 dark:border-yellow-500/20 bg-yellow-200/30 text-yellow-600 dark:bg-yellow-700/20 dark:text-yellow-200";
const red =
"border-red-600/40 dark:border-red-500/20 bg-red-200/30 text-red-600 dark:bg-red-700/20 dark:text-red-200";
const neutral =
"border-divider-light dark:border-divider-dark bg-black/5 text-gray-600 dark:bg-white/10 dark:text-gray-200";
export default function Alert({ children, type = AlertType.ALERT }: Props) {
return ( return (
<div className="flex flex-row items-center justify-center border border-yellow-600/40 dark:border-yellow-500/20 bg-yellow-200/30 text-yellow-600 dark:bg-yellow-700/20 dark:text-yellow-200 rounded-md py-2 scroll-px-40"> <div
className={clsx(
"flex flex-row items-center justify-center border rounded-md py-2 pr-2 scroll-px-40",
{
[yellow]: type === AlertType.ALERT,
[neutral]: type === AlertType.INFO,
}
)}
>
<ExclamationTriangleIcon className="flex-shrink-0 h-5 w-5 mr-2 ml-2" /> <ExclamationTriangleIcon className="flex-shrink-0 h-5 w-5 mr-2 ml-2" />
<span className="text-center text-sm">{children}</span> <span className="text-center text-sm">{children}</span>
</div> </div>

14
apps/login/ui/Info.tsx Normal file
View File

@@ -0,0 +1,14 @@
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
type Props = {
children: React.ReactNode;
};
export default function Alert({ children }: Props) {
return (
<div className="flex flex-row items-center justify-center border border-yellow-600/40 dark:border-yellow-500/20 bg-yellow-200/30 text-yellow-600 dark:bg-yellow-700/20 dark:text-yellow-200 rounded-md py-2 scroll-px-40">
<ExclamationTriangleIcon className="flex-shrink-0 h-5 w-5 mr-2 ml-2" />
<span className="text-center text-sm">{children}</span>
</div>
);
}

View File

@@ -1,8 +1,4 @@
import { createChannel, createClientFactory } from "nice-grpc"; import { createChannel, createClientFactory } from "nice-grpc";
import {
SettingsServiceClient,
SettingsServiceDefinition,
} from "./proto/server/zitadel/settings/v2alpha/settings_service";
import { authMiddleware } from "./middleware"; import { authMiddleware } from "./middleware";
import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions";