mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 08:23:16 +00:00
Merge branch 'qa' into idp-linking
This commit is contained in:
@@ -18,14 +18,19 @@ export async function POST(request: NextRequest) {
|
||||
const session = await getSession(sessionCookie.id, sessionCookie.token);
|
||||
|
||||
const userId = session?.session?.factors?.user?.id;
|
||||
|
||||
console.log("payload", {
|
||||
passkeyId,
|
||||
passkeyName,
|
||||
publicKeyCredential,
|
||||
userId,
|
||||
});
|
||||
if (userId) {
|
||||
return verifyPasskeyRegistration(
|
||||
return verifyPasskeyRegistration({
|
||||
passkeyId,
|
||||
passkeyName,
|
||||
publicKeyCredential,
|
||||
userId,
|
||||
)
|
||||
})
|
||||
.then((resp) => {
|
||||
return NextResponse.json(resp);
|
||||
})
|
||||
|
||||
@@ -22,12 +22,15 @@ export async function POST(request: NextRequest) {
|
||||
const userId = session?.session?.factors?.user?.id;
|
||||
|
||||
if (userId) {
|
||||
const req: PlainMessage<VerifyU2FRegistrationRequest> = {
|
||||
let req: PlainMessage<VerifyU2FRegistrationRequest> = {
|
||||
publicKeyCredential,
|
||||
u2fId,
|
||||
userId,
|
||||
tokenName: passkeyName,
|
||||
};
|
||||
|
||||
req = VerifyU2FRegistrationRequest.fromJson(request as any);
|
||||
|
||||
return verifyU2FRegistration(req)
|
||||
.then((resp) => {
|
||||
return NextResponse.json(resp);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { RequestChallenges } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
import {
|
||||
RetrieveIdentityProviderIntentRequest,
|
||||
VerifyPasskeyRegistrationRequest,
|
||||
VerifyU2FRegistrationRequest,
|
||||
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
import { IDPInformation } from "@zitadel/proto/zitadel/user/v2/idp_pb";
|
||||
@@ -482,24 +483,11 @@ export async function getActiveIdentityProviders(orgId?: string) {
|
||||
* @returns the newly set email
|
||||
*/
|
||||
export async function verifyPasskeyRegistration(
|
||||
passkeyId: string,
|
||||
passkeyName: string,
|
||||
publicKeyCredential:
|
||||
| {
|
||||
[key: string]: any;
|
||||
}
|
||||
| undefined,
|
||||
userId: string,
|
||||
request: PartialMessage<VerifyPasskeyRegistrationRequest>,
|
||||
) {
|
||||
return userService.verifyPasskeyRegistration(
|
||||
{
|
||||
passkeyId,
|
||||
passkeyName,
|
||||
publicKeyCredential,
|
||||
userId,
|
||||
},
|
||||
{},
|
||||
);
|
||||
// TODO: find a better way to handle this
|
||||
request = VerifyPasskeyRegistrationRequest.fromJson(request as any);
|
||||
return userService.verifyPasskeyRegistration(request, {});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,11 +18,14 @@ export function middleware(request: NextRequest) {
|
||||
requestHeaders.set("x-zitadel-login-client", SERVICE_USER_ID);
|
||||
|
||||
// this is a workaround for the next.js server not forwarding the host header
|
||||
requestHeaders.set("x-zitadel-forwarded", `host="${request.nextUrl.host}"`);
|
||||
// requestHeaders.set("x-zitadel-public-host", `${request.nextUrl.host}`);
|
||||
// requestHeaders.set("x-zitadel-forwarded", `host="${request.nextUrl.host}"`);
|
||||
requestHeaders.set("x-zitadel-public-host", `${request.nextUrl.host}`);
|
||||
|
||||
// this is a workaround for the next.js server not forwarding the host header
|
||||
// requestHeaders.set("x-zitadel-instance-host", `${INSTANCE}`);
|
||||
requestHeaders.set(
|
||||
"x-zitadel-instance-host",
|
||||
`${INSTANCE}`.replace("https://", ""),
|
||||
);
|
||||
|
||||
const responseHeaders = new Headers();
|
||||
responseHeaders.set("Access-Control-Allow-Origin", "*");
|
||||
|
||||
@@ -8,6 +8,7 @@ import Alert from "./Alert";
|
||||
import { Spinner } from "./Spinner";
|
||||
import BackButton from "./BackButton";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { RequestChallenges } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
|
||||
// either loginName or sessionId must be provided
|
||||
type Props = {
|
||||
@@ -78,7 +79,7 @@ export default function LoginPasskey({
|
||||
loginName,
|
||||
sessionId,
|
||||
organization,
|
||||
challenges: {
|
||||
challenges: RequestChallenges.fromJson({
|
||||
webAuthN: {
|
||||
domain: "",
|
||||
// USER_VERIFICATION_REQUIREMENT_UNSPECIFIED = 0;
|
||||
@@ -87,7 +88,7 @@ export default function LoginPasskey({
|
||||
// USER_VERIFICATION_REQUIREMENT_DISCOURAGED = 3; - mfa
|
||||
userVerificationRequirement: userVerificationRequirement,
|
||||
},
|
||||
},
|
||||
}),
|
||||
authRequestId,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -92,7 +92,7 @@ export default function RegisterPasskey({
|
||||
return submitRegister().then((resp: RegisterPasskeyResponse) => {
|
||||
const passkeyId = resp.passkeyId;
|
||||
const options: CredentialCreationOptions =
|
||||
(resp.publicKeyCredentialCreationOptions?.toJson() as CredentialCreationOptions) ??
|
||||
(resp.publicKeyCredentialCreationOptions as CredentialCreationOptions) ??
|
||||
{};
|
||||
|
||||
if (options?.publicKey) {
|
||||
@@ -143,6 +143,7 @@ export default function RegisterPasskey({
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
return submitVerify(passkeyId, "", data, sessionId).then(() => {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
@@ -194,19 +195,32 @@ export default function RegisterPasskey({
|
||||
type="button"
|
||||
variant={ButtonVariants.Secondary}
|
||||
onClick={() => {
|
||||
const params = new URLSearchParams();
|
||||
if (authRequestId) {
|
||||
params.set("authRequest", authRequestId);
|
||||
}
|
||||
if (sessionId) {
|
||||
params.set("sessionId", sessionId);
|
||||
}
|
||||
const params = new URLSearchParams({
|
||||
authRequest: authRequestId,
|
||||
});
|
||||
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
}
|
||||
if (sessionId) {
|
||||
params.set("sessionId", sessionId);
|
||||
}
|
||||
|
||||
router.push("/login?" + params);
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
}
|
||||
|
||||
router.push("/login?" + params);
|
||||
} else {
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (sessionId) {
|
||||
params.append("sessionId", sessionId);
|
||||
}
|
||||
if (organization) {
|
||||
params.append("organization", organization);
|
||||
}
|
||||
|
||||
router.push("/signedin?" + params);
|
||||
}
|
||||
}}
|
||||
>
|
||||
skip
|
||||
|
||||
@@ -90,7 +90,7 @@ export default function RegisterU2F({
|
||||
return submitRegister().then((resp: RegisterU2FResponse) => {
|
||||
const u2fId = resp.u2fId;
|
||||
const options: CredentialCreationOptions =
|
||||
(resp.publicKeyCredentialCreationOptions?.toJson() as CredentialCreationOptions) ??
|
||||
(resp.publicKeyCredentialCreationOptions as CredentialCreationOptions) ??
|
||||
{};
|
||||
|
||||
if (options.publicKey) {
|
||||
|
||||
@@ -121,11 +121,12 @@ export default function SessionItem({
|
||||
|
||||
<XCircleIcon
|
||||
className="hidden group-hover:block h-5 w-5 transition-all opacity-50 hover:opacity-100"
|
||||
onClick={() =>
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
clearSession(session.id).then(() => {
|
||||
reload();
|
||||
})
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -38,7 +38,6 @@ export async function createSessionAndUpdateCookie(
|
||||
? {
|
||||
user: { search: { case: "loginName", value: loginName } },
|
||||
password: { password },
|
||||
// totp: { code: totpCode },
|
||||
}
|
||||
: { user: { search: { case: "loginName", value: loginName } } },
|
||||
challenges,
|
||||
@@ -50,7 +49,7 @@ export async function createSessionAndUpdateCookie(
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: any = {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
@@ -103,7 +102,7 @@ export async function createSessionForUserIdAndUpdateCookie(
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: any = {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
@@ -153,7 +152,7 @@ export async function createSessionForIdpAndUpdateCookie(
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: any = {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
|
||||
@@ -2,39 +2,20 @@
|
||||
|
||||
import { ReactNode, forwardRef } from "react";
|
||||
import { SignInWithIdentityProviderProps } from "./SignInWith";
|
||||
import { IdpButtonClasses } from "./classes";
|
||||
|
||||
export const SignInWithAzureAD = forwardRef<
|
||||
HTMLButtonElement,
|
||||
SignInWithIdentityProviderProps
|
||||
>(
|
||||
export const SignInWithAzureAD = forwardRef<HTMLButtonElement, SignInWithIdentityProviderProps>(
|
||||
({ children, className = "", name = "", ...props }, ref): ReactNode => (
|
||||
<button
|
||||
type="button"
|
||||
ref={ref}
|
||||
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
|
||||
{...props}
|
||||
>
|
||||
<button type="button" ref={ref} className={`${IdpButtonClasses} ${className}`} {...props}>
|
||||
<div className="ztdl-h-12 ztdl-p-[10px] ztdl-w-12 ztdl-flex ztdl-items-center ztdl-justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="21"
|
||||
height="21"
|
||||
viewBox="0 0 21 21"
|
||||
className="w-full h-full"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" className="w-full h-full">
|
||||
<path fill="#f25022" d="M1 1H10V10H1z"></path>
|
||||
<path fill="#00a4ef" d="M1 11H10V20H1z"></path>
|
||||
<path fill="#7fba00" d="M11 1H20V10H11z"></path>
|
||||
<path fill="#ffb900" d="M11 11H20V20H11z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<span className="ztdl-ml-4">
|
||||
{name ? name : "Sign in with AzureAD"}
|
||||
</span>
|
||||
)}
|
||||
{children ? children : <span className="ztdl-ml-4">{name ? name : "Sign in with AzureAD"}</span>}
|
||||
</button>
|
||||
),
|
||||
);
|
||||
|
||||
@@ -2,18 +2,11 @@
|
||||
|
||||
import { ReactNode, forwardRef } from "react";
|
||||
import { SignInWithIdentityProviderProps } from "./SignInWith";
|
||||
import { IdpButtonClasses } from "./classes";
|
||||
|
||||
export const SignInWithGithub = forwardRef<
|
||||
HTMLButtonElement,
|
||||
SignInWithIdentityProviderProps
|
||||
>(
|
||||
export const SignInWithGithub = forwardRef<HTMLButtonElement, SignInWithIdentityProviderProps>(
|
||||
({ children, className = "", name = "", ...props }, ref): ReactNode => (
|
||||
<button
|
||||
type="button"
|
||||
ref={ref}
|
||||
className={`ztdl-h-[50px] ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
|
||||
{...props}
|
||||
>
|
||||
<button type="button" ref={ref} className={`${IdpButtonClasses} ${className}`} {...props}>
|
||||
<div className="ztdl-h-8 ztdl-w-8 ztdl-mx-2 flex items-center justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@@ -46,11 +39,7 @@ export const SignInWithGithub = forwardRef<
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<span className="ztdl-ml-4">{name ? name : "Sign in with GitHub"}</span>
|
||||
)}
|
||||
{children ? children : <span className="ztdl-ml-4">{name ? name : "Sign in with GitHub"}</span>}
|
||||
</button>
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import { ReactNode, forwardRef } from "react";
|
||||
import { SignInWithIdentityProviderProps } from "./SignInWith";
|
||||
import { IdpButtonClasses } from "./classes";
|
||||
|
||||
export const SignInWithGitlab = forwardRef<
|
||||
HTMLButtonElement,
|
||||
SignInWithIdentityProviderProps
|
||||
>(
|
||||
export const SignInWithGitlab = forwardRef<HTMLButtonElement, SignInWithIdentityProviderProps>(
|
||||
({ children, className = "", name = "", ...props }, ref): ReactNode => (
|
||||
<button
|
||||
type="button"
|
||||
ref={ref}
|
||||
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
|
||||
{...props}
|
||||
>
|
||||
<button type="button" ref={ref} className={`${IdpButtonClasses} ${className}`} {...props}>
|
||||
<div className="ztdl-h-12 ztdl-w-12 flex items-center justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={25}
|
||||
height={24}
|
||||
fill="none"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={25} height={24} fill="none">
|
||||
<path
|
||||
fill="#e24329"
|
||||
d="m24.507 9.5-.034-.09L21.082.562a.896.896 0 0 0-1.694.091l-2.29 7.01H7.825L5.535.653a.898.898 0 0 0-1.694-.09L.451 9.411.416 9.5a6.297 6.297 0 0 0 2.09 7.278l.012.01.03.022 5.16 3.867 2.56 1.935 1.554 1.176a1.051 1.051 0 0 0 1.268 0l1.555-1.176 2.56-1.935 5.197-3.89.014-.01A6.297 6.297 0 0 0 24.507 9.5z"
|
||||
@@ -37,11 +25,7 @@ export const SignInWithGitlab = forwardRef<
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<span className="ztdl-ml-4">{name ? name : "Sign in with GitLab"}</span>
|
||||
)}
|
||||
{children ? children : <span className="ztdl-ml-4">{name ? name : "Sign in with GitLab"}</span>}
|
||||
</button>
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,24 +1,12 @@
|
||||
import { ReactNode, forwardRef } from "react";
|
||||
import { SignInWithIdentityProviderProps } from "./SignInWith";
|
||||
import { IdpButtonClasses } from "./classes";
|
||||
|
||||
export const SignInWithGoogle = forwardRef<
|
||||
HTMLButtonElement,
|
||||
SignInWithIdentityProviderProps
|
||||
>(
|
||||
export const SignInWithGoogle = forwardRef<HTMLButtonElement, SignInWithIdentityProviderProps>(
|
||||
({ children, className = "", name = "", ...props }, ref): ReactNode => (
|
||||
<button
|
||||
type="button"
|
||||
ref={ref}
|
||||
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
|
||||
{...props}
|
||||
>
|
||||
<button type="button" ref={ref} className={`${IdpButtonClasses} ${className}`} {...props}>
|
||||
<div className="ztdl-h-12 ztdl-w-12 ztdl-flex ztdl-items-center ztdl-justify-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlSpace="preserve"
|
||||
id="Capa_1"
|
||||
viewBox="0 0 150 150"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlSpace="preserve" id="Capa_1" viewBox="0 0 150 150">
|
||||
<style>
|
||||
{
|
||||
".st0{fill:#1a73e8}.st1{fill:#ea4335}.st2{fill:#4285f4}.st3{fill:#fbbc04}.st4{fill:#34a853}.st5{fill:#4caf50}.st6{fill:#1e88e5}.st7{fill:#e53935}.st8{fill:#c62828}.st9{fill:#fbc02d}.st10{fill:#1565c0}.st11{fill:#2e7d32}.st16{clip-path:url(#SVGID_2_)}.st17{fill:#188038}.st18,.st19{opacity:.2;fill:#fff;enable-background:new}.st19{opacity:.3;fill:#0d652d}.st20{clip-path:url(#SVGID_4_)}.st21{opacity:.3;fill:url(#_45_shadow_1_);enable-background:new}.st22{clip-path:url(#SVGID_6_)}.st23{fill:#fa7b17}.st24,.st25,.st26{opacity:.3;fill:#174ea6;enable-background:new}.st25,.st26{fill:#a50e0e}.st26{fill:#e37400}.st27{fill:url(#Finish_mask_1_)}.st28{fill:#fff}.st29{fill:#0c9d58}.st30,.st31{opacity:.2;fill:#004d40;enable-background:new}.st31{fill:#3e2723}.st32{fill:#ffc107}.st33{fill:#1a237e;enable-background:new}.st33,.st34{opacity:.2}.st35{fill:#1a237e}.st36{fill:url(#SVGID_7_)}.st37{fill:#fbbc05}.st38{clip-path:url(#SVGID_9_);fill:#e53935}.st39{clip-path:url(#SVGID_11_);fill:#fbc02d}.st40{clip-path:url(#SVGID_13_);fill:#e53935}.st41{clip-path:url(#SVGID_15_);fill:#fbc02d}"
|
||||
@@ -50,11 +38,7 @@ export const SignInWithGoogle = forwardRef<
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
{children ? (
|
||||
children
|
||||
) : (
|
||||
<span className="ztdl-ml-4">{name ? name : "Sign in with Google"}</span>
|
||||
)}
|
||||
{children ? children : <span className="ztdl-ml-4">{name ? name : "Sign in with Google"}</span>}
|
||||
</button>
|
||||
),
|
||||
);
|
||||
|
||||
2
packages/zitadel-react/src/components/classes.ts
Normal file
2
packages/zitadel-react/src/components/classes.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export const IdpButtonClasses =
|
||||
"transition-all ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center bg-background-light-400 text-text-light-500 dark:bg-background-dark-500 dark:text-text-dark-500 border border-divider-light hover:border-black dark:border-divider-dark hover:dark:border-white focus:border-primary-light-500 focus:dark:border-primary-dark-500 outline-none rounded-md px-4 text-sm";
|
||||
Reference in New Issue
Block a user