mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 02:02:23 +00:00
Merge branch 'main' into idp-linking
This commit is contained in:
21
.github/dependabot.yml
vendored
Normal file
21
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: '/'
|
||||
open-pull-requests-limit: 1
|
||||
schedule:
|
||||
interval: 'daily'
|
||||
|
||||
- package-ecosystem: npm
|
||||
directory: '/'
|
||||
open-pull-requests-limit: 3
|
||||
schedule:
|
||||
interval: daily
|
||||
groups:
|
||||
prod:
|
||||
dependency-type: production
|
||||
dev:
|
||||
dependency-type: development
|
||||
ignore:
|
||||
- dependency-name: "eslint"
|
||||
versions: [ "9.x" ]
|
||||
6
.github/workflows/issues.yml
vendored
6
.github/workflows/issues.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: add issue
|
||||
uses: actions/add-to-project@v0.5.0
|
||||
uses: actions/add-to-project@v1.0.1
|
||||
if: ${{ github.event_name == 'issues' }}
|
||||
with:
|
||||
# You can target a repository in a different organization
|
||||
@@ -28,14 +28,14 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
- name: add pr
|
||||
uses: actions/add-to-project@v0.5.0
|
||||
uses: actions/add-to-project@v1.0.1
|
||||
if: ${{ github.event_name == 'pull_request_target' && github.actor != 'dependabot[bot]' && !contains(steps.checkUserMember.outputs.teams, 'engineers')}}
|
||||
with:
|
||||
# You can target a repository in a different organization
|
||||
# to the issue
|
||||
project-url: https://github.com/orgs/zitadel/projects/2
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
- uses: actions-ecosystem/action-add-labels@v1.1.0
|
||||
- uses: actions-ecosystem/action-add-labels@v1.1.3
|
||||
if: ${{ github.event_name == 'pull_request_target' && github.actor != 'dependabot[bot]' && !contains(steps.checkUserMember.outputs.teams, 'staff')}}
|
||||
with:
|
||||
github_token: ${{ secrets.ADD_TO_PROJECT_PAT }}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -14,7 +14,6 @@ server/dist
|
||||
public/dist
|
||||
.turbo
|
||||
packages/zitadel-server/src/app/proto
|
||||
packages/zitadel-client/src/app/proto
|
||||
.vscode
|
||||
.idea
|
||||
.vercel
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
.next/
|
||||
dist/
|
||||
packages/zitadel-proto/zitadel
|
||||
|
||||
5
.prettierrc.json
Normal file
5
.prettierrc.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"printWidth": 125,
|
||||
"trailingComma": "all",
|
||||
"plugins": ["prettier-plugin-organize-imports"]
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
ZITADEL_API_URL=http://localhost:22222
|
||||
ZITADEL_API_URL=http://localhost:22222
|
||||
DEBUG=true
|
||||
@@ -2,7 +2,7 @@ import { stub } from "../support/mock";
|
||||
|
||||
describe("login", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.session.v2beta.SessionService", "CreateSession", {
|
||||
stub("zitadel.session.v2.SessionService", "CreateSession", {
|
||||
data: {
|
||||
details: {
|
||||
sequence: 859,
|
||||
@@ -16,7 +16,7 @@ describe("login", () => {
|
||||
},
|
||||
});
|
||||
|
||||
stub("zitadel.session.v2beta.SessionService", "GetSession", {
|
||||
stub("zitadel.session.v2.SessionService", "GetSession", {
|
||||
data: {
|
||||
session: {
|
||||
id: "221394658884845598",
|
||||
@@ -37,7 +37,7 @@ describe("login", () => {
|
||||
},
|
||||
});
|
||||
|
||||
stub("zitadel.settings.v2beta.SettingsService", "GetLoginSettings", {
|
||||
stub("zitadel.settings.v2.SettingsService", "GetLoginSettings", {
|
||||
data: {
|
||||
settings: {
|
||||
passkeysType: 1,
|
||||
@@ -47,7 +47,7 @@ describe("login", () => {
|
||||
});
|
||||
describe("password login", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.user.v2beta.UserService", "ListUsers", {
|
||||
stub("zitadel.user.v2.UserService", "ListUsers", {
|
||||
data: {
|
||||
details: {
|
||||
totalResult: 1,
|
||||
@@ -79,7 +79,7 @@ describe("login", () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
stub("zitadel.user.v2beta.UserService", "ListAuthenticationMethodTypes", {
|
||||
stub("zitadel.user.v2.UserService", "ListAuthenticationMethodTypes", {
|
||||
data: {
|
||||
authMethodTypes: [1], // 1 for password authentication
|
||||
},
|
||||
@@ -91,7 +91,7 @@ describe("login", () => {
|
||||
});
|
||||
describe("with passkey prompt", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.session.v2beta.SessionService", "SetSession", {
|
||||
stub("zitadel.session.v2.SessionService", "SetSession", {
|
||||
data: {
|
||||
details: {
|
||||
sequence: 859,
|
||||
@@ -118,7 +118,7 @@ describe("login", () => {
|
||||
});
|
||||
describe("passkey login", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.user.v2beta.UserService", "ListUsers", {
|
||||
stub("zitadel.user.v2.UserService", "ListUsers", {
|
||||
data: {
|
||||
details: {
|
||||
totalResult: 1,
|
||||
@@ -150,7 +150,7 @@ describe("login", () => {
|
||||
],
|
||||
},
|
||||
});
|
||||
stub("zitadel.user.v2beta.UserService", "ListAuthenticationMethodTypes", {
|
||||
stub("zitadel.user.v2.UserService", "ListAuthenticationMethodTypes", {
|
||||
data: {
|
||||
authMethodTypes: [2], // 2 for passwordless authentication
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ const IDP_URL = "https://example.com/idp/url";
|
||||
|
||||
describe("register idps", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.user.v2beta.UserService", "StartIdentityProviderIntent", {
|
||||
stub("zitadel.user.v2.UserService", "StartIdentityProviderIntent", {
|
||||
data: {
|
||||
authUrl: IDP_URL,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import { stub } from "../support/mock";
|
||||
|
||||
describe("register", () => {
|
||||
beforeEach(() => {
|
||||
stub("zitadel.user.v2beta.UserService", "AddHumanUser", {
|
||||
stub("zitadel.user.v2.UserService", "AddHumanUser", {
|
||||
data: {
|
||||
userId: "123",
|
||||
},
|
||||
|
||||
@@ -2,12 +2,12 @@ import { stub } from "../support/mock";
|
||||
|
||||
describe("/verify", () => {
|
||||
it("redirects after successful email verification", () => {
|
||||
stub("zitadel.user.v2beta.UserService", "VerifyEmail");
|
||||
stub("zitadel.user.v2.UserService", "VerifyEmail");
|
||||
cy.visit("/verify?userId=123&code=abc&submit=true");
|
||||
cy.location("pathname", { timeout: 10_000 }).should("eq", "/loginname");
|
||||
});
|
||||
it("shows an error if validation failed", () => {
|
||||
stub("zitadel.user.v2beta.UserService", "VerifyEmail", {
|
||||
stub("zitadel.user.v2.UserService", "VerifyEmail", {
|
||||
code: 3,
|
||||
error: "error validating code",
|
||||
});
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
[
|
||||
{
|
||||
"service": "zitadel.settings.v2beta.SettingsService",
|
||||
"service": "zitadel.settings.v2.SettingsService",
|
||||
"method": "GetBrandingSettings",
|
||||
"out": {}
|
||||
},
|
||||
{
|
||||
"service": "zitadel.settings.v2beta.SettingsService",
|
||||
"service": "zitadel.settings.v2.SettingsService",
|
||||
"method": "GetLegalAndSupportSettings",
|
||||
"out": {
|
||||
"data": {
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"service": "zitadel.settings.v2beta.SettingsService",
|
||||
"service": "zitadel.settings.v2.SettingsService",
|
||||
"method": "GetActiveIdentityProviders",
|
||||
"out": {
|
||||
"data": {
|
||||
@@ -33,7 +33,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"service": "zitadel.settings.v2beta.SettingsService",
|
||||
"service": "zitadel.settings.v2.SettingsService",
|
||||
"method": "GetPasswordComplexitySettings",
|
||||
"out": {
|
||||
"data": {
|
||||
@@ -1,6 +1,6 @@
|
||||
zitadel/user/v2beta/user_service.proto
|
||||
zitadel/session/v2beta/session_service.proto
|
||||
zitadel/settings/v2beta/settings_service.proto
|
||||
zitadel/user/v2/user_service.proto
|
||||
zitadel/session/v2/session_service.proto
|
||||
zitadel/settings/v2/settings_service.proto
|
||||
zitadel/management.proto
|
||||
zitadel/auth.proto
|
||||
zitadel/admin.proto
|
||||
@@ -33,9 +33,6 @@ const secureHeaders = [
|
||||
const nextConfig = {
|
||||
reactStrictMode: true, // Recommended for the `pages` directory, default in `app`.
|
||||
swcMinify: true,
|
||||
experimental: {
|
||||
serverActions: true,
|
||||
},
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
|
||||
@@ -36,51 +36,52 @@
|
||||
"@heroicons/react": "2.1.3",
|
||||
"@tailwindcss/forms": "0.5.7",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"@zitadel/client2": "workspace:*",
|
||||
"@zitadel/react": "workspace:*",
|
||||
"@zitadel/client": "workspace:*",
|
||||
"@zitadel/next": "workspace:*",
|
||||
"@zitadel/node": "workspace:*",
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"@zitadel/react": "workspace:*",
|
||||
"clsx": "1.2.1",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"moment": "^2.29.4",
|
||||
"next": "14.2.3",
|
||||
"next": "14.2.5",
|
||||
"next-themes": "^0.2.1",
|
||||
"nice-grpc": "2.0.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "18.3.1",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "18.3.1",
|
||||
"react-hook-form": "7.39.5",
|
||||
"swr": "^2.2.0",
|
||||
"tinycolor2": "1.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bufbuild/buf": "^1.14.0",
|
||||
"@bufbuild/buf": "^1.36.0",
|
||||
"@testing-library/jest-dom": "^6.4.5",
|
||||
"@testing-library/react": "^15.0.7",
|
||||
"@types/ms": "0.7.31",
|
||||
"@types/node": "18.11.9",
|
||||
"@types/react": "18.2.8",
|
||||
"@types/react-dom": "18.0.9",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@types/ms": "0.7.34",
|
||||
"@types/node": "22.1.0",
|
||||
"@types/react": "18.3.3",
|
||||
"@types/react-dom": "18.3.0",
|
||||
"@types/tinycolor2": "1.4.3",
|
||||
"@types/uuid": "^9.0.1",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vercel/git-hooks": "1.0.0",
|
||||
"@zitadel/prettier-config": "workspace:*",
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"autoprefixer": "10.4.13",
|
||||
"autoprefixer": "10.4.20",
|
||||
"concurrently": "^8.1.0",
|
||||
"cypress": "^13.9.0",
|
||||
"del-cli": "5.0.0",
|
||||
"cypress": "^13.13.2",
|
||||
"del-cli": "5.1.0",
|
||||
"env-cmd": "^10.1.0",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"grpc-tools": "1.11.3",
|
||||
"lint-staged": "13.0.3",
|
||||
"make-dir-cli": "3.0.0",
|
||||
"nodemon": "^2.0.22",
|
||||
"postcss": "8.4.21",
|
||||
"prettier-plugin-tailwindcss": "0.1.13",
|
||||
"grpc-tools": "1.12.4",
|
||||
"lint-staged": "15.2.8",
|
||||
"make-dir-cli": "4.0.0",
|
||||
"nodemon": "^3.1.4",
|
||||
"postcss": "8.4.41",
|
||||
"prettier-plugin-tailwindcss": "0.6.5",
|
||||
"sass": "^1.77.1",
|
||||
"start-server-and-test": "^2.0.0",
|
||||
"tailwindcss": "3.2.4",
|
||||
"tailwindcss": "3.4.9",
|
||||
"ts-proto": "^1.139.0",
|
||||
"typescript": "^5.4.5",
|
||||
"zitadel-tailwind-config": "workspace:*"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getBrandingSettings, listSessions } from "@/lib/zitadel";
|
||||
import { getAllSessionCookieIds } from "@/utils/cookies";
|
||||
import { getAllSessionCookieIds } from "@zitadel/next";
|
||||
import { UserPlusIcon } from "@heroicons/react/24/outline";
|
||||
import Link from "next/link";
|
||||
import SessionsList from "@/ui/SessionsList";
|
||||
|
||||
@@ -1,14 +1,7 @@
|
||||
import { ProviderSlug } from "@/lib/demos";
|
||||
import { getBrandingSettings } from "@/lib/zitadel";
|
||||
import { getBrandingSettings, PROVIDER_NAME_MAPPING } from "@/lib/zitadel";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
|
||||
const PROVIDER_NAME_MAPPING: {
|
||||
[provider: string]: string;
|
||||
} = {
|
||||
[ProviderSlug.GOOGLE]: "Google",
|
||||
[ProviderSlug.GITHUB]: "GitHub",
|
||||
};
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
params,
|
||||
|
||||
@@ -8,6 +8,104 @@ import {
|
||||
import Alert, { AlertType } from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import IdpSignin from "@/ui/IdpSignin";
|
||||
import { AddHumanUserRequest } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
import { IDPInformation, IDPLink } from "@zitadel/proto/zitadel/user/v2/idp_pb";
|
||||
import { PartialMessage } from "@zitadel/client";
|
||||
|
||||
const PROVIDER_MAPPING: {
|
||||
[provider: string]: (
|
||||
rI: IDPInformation,
|
||||
) => PartialMessage<AddHumanUserRequest>;
|
||||
} = {
|
||||
[ProviderSlug.GOOGLE]: (idp: IDPInformation) => {
|
||||
const rawInfo = idp.rawInformation?.toJson() as {
|
||||
User: {
|
||||
email: string;
|
||||
name?: string;
|
||||
given_name?: string;
|
||||
family_name?: string;
|
||||
};
|
||||
};
|
||||
|
||||
const idpLink: PartialMessage<IDPLink> = {
|
||||
idpId: idp.idpId,
|
||||
userId: idp.userId,
|
||||
userName: idp.userName,
|
||||
};
|
||||
|
||||
const req: PartialMessage<AddHumanUserRequest> = {
|
||||
username: idp.userName,
|
||||
email: {
|
||||
email: rawInfo.User?.email,
|
||||
verification: { case: "isVerified", value: true },
|
||||
},
|
||||
// organisation: Organisation | undefined;
|
||||
profile: {
|
||||
displayName: rawInfo.User?.name ?? "",
|
||||
givenName: rawInfo.User?.given_name ?? "",
|
||||
familyName: rawInfo.User?.family_name ?? "",
|
||||
},
|
||||
idpLinks: [idpLink],
|
||||
};
|
||||
return req;
|
||||
},
|
||||
[ProviderSlug.AZURE]: (idp: IDPInformation) => {
|
||||
const rawInfo = idp.rawInformation?.toJson() as {
|
||||
mail: string;
|
||||
displayName?: string;
|
||||
givenName?: string;
|
||||
surname?: string;
|
||||
};
|
||||
|
||||
const idpLink: PartialMessage<IDPLink> = {
|
||||
idpId: idp.idpId,
|
||||
userId: idp.userId,
|
||||
userName: idp.userName,
|
||||
};
|
||||
|
||||
const req: PartialMessage<AddHumanUserRequest> = {
|
||||
username: idp.userName,
|
||||
email: {
|
||||
email: rawInfo?.mail,
|
||||
verification: { case: "isVerified", value: true },
|
||||
},
|
||||
// organisation: Organisation | undefined;
|
||||
profile: {
|
||||
displayName: rawInfo?.displayName ?? "",
|
||||
givenName: rawInfo?.givenName ?? "",
|
||||
familyName: rawInfo?.surname ?? "",
|
||||
},
|
||||
idpLinks: [idpLink],
|
||||
};
|
||||
return req;
|
||||
},
|
||||
[ProviderSlug.GITHUB]: (idp: IDPInformation) => {
|
||||
const rawInfo = idp.rawInformation?.toJson() as {
|
||||
email: string;
|
||||
name: string;
|
||||
};
|
||||
const idpLink: PartialMessage<IDPLink> = {
|
||||
idpId: idp.idpId,
|
||||
userId: idp.userId,
|
||||
userName: idp.userName,
|
||||
};
|
||||
const req: PartialMessage<AddHumanUserRequest> = {
|
||||
username: idp.userName,
|
||||
email: {
|
||||
email: rawInfo?.email,
|
||||
verification: { case: "isVerified", value: true },
|
||||
},
|
||||
// organisation: Organisation | undefined;
|
||||
profile: {
|
||||
displayName: rawInfo?.name ?? "",
|
||||
givenName: rawInfo?.name ?? "",
|
||||
familyName: rawInfo?.name ?? "",
|
||||
},
|
||||
idpLinks: [idpLink],
|
||||
};
|
||||
return req;
|
||||
},
|
||||
};
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
} from "@/lib/zitadel";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import { SignInWithIDP } from "@/ui/SignInWithIDP";
|
||||
import { makeReqCtx } from "@zitadel/client2/v2beta";
|
||||
import { makeReqCtx } from "@zitadel/client/v2";
|
||||
|
||||
function getIdentityProviders(orgId?: string) {
|
||||
return settingsService
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import { SignInWithIDP } from "@/ui/SignInWithIDP";
|
||||
import UsernameForm from "@/ui/UsernameForm";
|
||||
import { makeReqCtx } from "@zitadel/client2/v2beta";
|
||||
import { makeReqCtx } from "@zitadel/client/v2";
|
||||
|
||||
function getIdentityProviders(orgId?: string) {
|
||||
return settingsService
|
||||
@@ -51,16 +51,16 @@ export default async function Page({
|
||||
organization={organization}
|
||||
submit={submit}
|
||||
allowRegister={!!loginSettings?.allowRegister}
|
||||
/>
|
||||
|
||||
{legal && identityProviders && process.env.ZITADEL_API_URL && (
|
||||
<SignInWithIDP
|
||||
host={host}
|
||||
identityProviders={identityProviders}
|
||||
authRequestId={authRequestId}
|
||||
organization={organization}
|
||||
></SignInWithIDP>
|
||||
)}
|
||||
>
|
||||
{legal && identityProviders && process.env.ZITADEL_API_URL && (
|
||||
<SignInWithIDP
|
||||
host={host}
|
||||
identityProviders={identityProviders}
|
||||
authRequestId={authRequestId}
|
||||
organization={organization}
|
||||
></SignInWithIDP>
|
||||
)}
|
||||
</UsernameForm>
|
||||
</div>
|
||||
</DynamicTheme>
|
||||
);
|
||||
|
||||
@@ -2,16 +2,14 @@ import {
|
||||
getBrandingSettings,
|
||||
getSession,
|
||||
listAuthenticationMethodTypes,
|
||||
sessionService,
|
||||
} from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import BackButton from "@/ui/BackButton";
|
||||
import ChooseSecondFactor from "@/ui/ChooseSecondFactor";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import {
|
||||
getMostRecentCookieWithLoginname,
|
||||
getSessionCookieById,
|
||||
} from "@/utils/cookies";
|
||||
import { getSessionCookieById, loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -29,26 +27,25 @@ export default async function Page({
|
||||
loginName?: string,
|
||||
organization?: string,
|
||||
) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
return loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session && response.session.factors?.user?.id) {
|
||||
return listAuthenticationMethodTypes(
|
||||
response.session.factors.user.id,
|
||||
).then((methods) => {
|
||||
return {
|
||||
factors: response.session?.factors,
|
||||
authMethods: methods.authMethodTypes ?? [],
|
||||
};
|
||||
});
|
||||
}).then((session) => {
|
||||
if (session && session.factors?.user?.id) {
|
||||
return listAuthenticationMethodTypes(session.factors.user.id).then(
|
||||
(methods) => {
|
||||
return {
|
||||
factors: session?.factors,
|
||||
authMethods: methods.authMethodTypes ?? [],
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function loadSessionById(sessionId: string, organization?: string) {
|
||||
const recent = await getSessionCookieById(sessionId, organization);
|
||||
const recent = await getSessionCookieById({ sessionId, organization });
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session && response.session.factors?.user?.id) {
|
||||
return listAuthenticationMethodTypes(
|
||||
|
||||
@@ -4,16 +4,14 @@ import {
|
||||
getSession,
|
||||
getUserByID,
|
||||
listAuthenticationMethodTypes,
|
||||
sessionService,
|
||||
} from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import BackButton from "@/ui/BackButton";
|
||||
import ChooseSecondFactorToSetup from "@/ui/ChooseSecondFactorToSetup";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import {
|
||||
getMostRecentCookieWithLoginname,
|
||||
getSessionCookieById,
|
||||
} from "@/utils/cookies";
|
||||
import { getSessionCookieById, loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -31,13 +29,12 @@ export default async function Page({
|
||||
loginName?: string,
|
||||
organization?: string,
|
||||
) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
return loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session && response.session.factors?.user?.id) {
|
||||
const userId = response.session.factors.user.id;
|
||||
}).then((session) => {
|
||||
if (session && session.factors?.user?.id) {
|
||||
const userId = session.factors.user.id;
|
||||
return listAuthenticationMethodTypes(userId).then((methods) => {
|
||||
return getUserByID(userId).then((user) => {
|
||||
const humanUser =
|
||||
@@ -46,7 +43,7 @@ export default async function Page({
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
factors: response.session?.factors,
|
||||
factors: session?.factors,
|
||||
authMethods: methods.authMethodTypes ?? [],
|
||||
phoneVerified: humanUser?.phone?.isVerified ?? false,
|
||||
emailVerified: humanUser?.email?.isVerified ?? false,
|
||||
@@ -58,7 +55,7 @@ export default async function Page({
|
||||
}
|
||||
|
||||
async function loadSessionById(sessionId: string, organization?: string) {
|
||||
const recent = await getSessionCookieById(sessionId, organization);
|
||||
const recent = await getSessionCookieById({ sessionId, organization });
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session && response.session.factors?.user?.id) {
|
||||
const userId = response.session.factors.user.id;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import {
|
||||
getBrandingSettings,
|
||||
getLoginSettings,
|
||||
getSession,
|
||||
} from "@/lib/zitadel";
|
||||
import { getBrandingSettings, sessionService } from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import LoginOTP from "@/ui/LoginOTP";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -21,21 +17,13 @@ export default async function Page({
|
||||
|
||||
const { method } = params;
|
||||
|
||||
const { session, token } = await loadSession(loginName, organization);
|
||||
const session = await loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
});
|
||||
|
||||
const branding = await getBrandingSettings(organization);
|
||||
|
||||
async function loadSession(loginName?: string, organization?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
return { session: response?.session, token: recent.token };
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<DynamicTheme branding={branding}>
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
|
||||
@@ -2,19 +2,18 @@ import {
|
||||
addOTPEmail,
|
||||
addOTPSMS,
|
||||
getBrandingSettings,
|
||||
getSession,
|
||||
registerTOTP,
|
||||
sessionService,
|
||||
} from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import BackButton from "@/ui/BackButton";
|
||||
import { Button, ButtonVariants } from "@/ui/Button";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import { Spinner } from "@/ui/Spinner";
|
||||
import TOTPRegister from "@/ui/TOTPRegister";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import Link from "next/link";
|
||||
import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -28,7 +27,10 @@ export default async function Page({
|
||||
const { method } = params;
|
||||
|
||||
const branding = await getBrandingSettings(organization);
|
||||
const { session, token } = await loadSession(loginName, organization);
|
||||
const session = await loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
});
|
||||
|
||||
let totpResponse: RegisterTOTPResponse | undefined,
|
||||
totpError: Error | undefined;
|
||||
@@ -56,17 +58,6 @@ export default async function Page({
|
||||
throw new Error("No session found");
|
||||
}
|
||||
|
||||
async function loadSession(loginName?: string, organization?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
return { session: response?.session, token: recent.token };
|
||||
});
|
||||
}
|
||||
|
||||
const paramsToContinue = new URLSearchParams({});
|
||||
let urlToContinue = "/accounts";
|
||||
|
||||
|
||||
45
apps/login/src/app/(login)/overview/page.tsx
Normal file
45
apps/login/src/app/(login)/overview/page.tsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { demos } from "@/lib/demos";
|
||||
import Link from "next/link";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20 mb-10">
|
||||
<div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500 px-8 py-12">
|
||||
<div className="space-y-8">
|
||||
<h1 className="text-xl font-medium">Pages</h1>
|
||||
|
||||
<div className="space-y-10">
|
||||
{demos.map((section) => {
|
||||
return (
|
||||
<div key={section.name} className="space-y-5">
|
||||
<div className="text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||
{section.name}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-5 lg:grid-cols-2">
|
||||
{section.items.map((item) => {
|
||||
return (
|
||||
<Link
|
||||
href={`/${item.slug}`}
|
||||
key={item.name}
|
||||
className="bg-background-light-400 dark:bg-background-dark-400 group block space-y-1.5 rounded-md px-5 py-3 hover:shadow-lg hover:dark:bg-white/10 border border-divider-light dark:border-divider-dark transition-all "
|
||||
>
|
||||
<div className="font-medium">{item.name}</div>
|
||||
|
||||
{item.description ? (
|
||||
<div className="line-clamp-3 text-sm text-text-light-secondary-500 dark:text-text-dark-secondary-500">
|
||||
{item.description}
|
||||
</div>
|
||||
) : null}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||
import { getBrandingSettings, sessionService } from "@/lib/zitadel";
|
||||
import Alert, { AlertType } from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import RegisterPasskey from "@/ui/RegisterPasskey";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -13,19 +13,11 @@ export default async function Page({
|
||||
const { loginName, promptPasswordless, organization, authRequestId } =
|
||||
searchParams;
|
||||
|
||||
const sessionFactors = await loadSession(loginName);
|
||||
const session = await loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
});
|
||||
|
||||
async function loadSession(loginName?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
}
|
||||
const title = !!promptPasswordless
|
||||
? "Authenticate with a passkey"
|
||||
: "Use your passkey to confirm it's really you";
|
||||
@@ -40,10 +32,10 @@ export default async function Page({
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<h1>{title}</h1>
|
||||
|
||||
{sessionFactors && (
|
||||
{session && (
|
||||
<UserAvatar
|
||||
loginName={loginName ?? sessionFactors.factors?.user?.loginName}
|
||||
displayName={sessionFactors.factors?.user?.displayName}
|
||||
loginName={loginName ?? session.factors?.user?.loginName}
|
||||
displayName={session.factors?.user?.displayName}
|
||||
showDropdown
|
||||
searchParams={searchParams}
|
||||
></UserAvatar>
|
||||
@@ -64,7 +56,7 @@ export default async function Page({
|
||||
</span>
|
||||
</Alert>
|
||||
|
||||
{!sessionFactors && (
|
||||
{!session && (
|
||||
<div className="py-4">
|
||||
<Alert>
|
||||
Could not get the context of the user. Make sure to enter the
|
||||
@@ -73,9 +65,9 @@ export default async function Page({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sessionFactors?.id && (
|
||||
{session?.id && (
|
||||
<RegisterPasskey
|
||||
sessionId={sessionFactors.id}
|
||||
sessionId={session.id}
|
||||
isPrompt={!!promptPasswordless}
|
||||
organization={organization}
|
||||
authRequestId={authRequestId}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||
import { getBrandingSettings, getSession, sessionService } from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import LoginPasskey from "@/ui/LoginPasskey";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import {
|
||||
getMostRecentCookieWithLoginname,
|
||||
getSessionCookieById,
|
||||
} from "@/utils/cookies";
|
||||
import { getSessionCookieById, loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
const title = "Authenticate with a passkey";
|
||||
const description =
|
||||
@@ -22,25 +19,10 @@ export default async function Page({
|
||||
|
||||
const sessionFactors = sessionId
|
||||
? await loadSessionById(sessionId, organization)
|
||||
: await loadSessionByLoginname(loginName, organization);
|
||||
|
||||
async function loadSessionByLoginname(
|
||||
loginName?: string,
|
||||
organization?: string,
|
||||
) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
}
|
||||
: await loadMostRecentSession(sessionService, { loginName, organization });
|
||||
|
||||
async function loadSessionById(sessionId: string, organization?: string) {
|
||||
const recent = await getSessionCookieById(sessionId, organization);
|
||||
const recent = await getSessionCookieById({ sessionId, organization });
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import {
|
||||
getBrandingSettings,
|
||||
getLoginSettings,
|
||||
getSession,
|
||||
sessionService,
|
||||
} from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import PasswordForm from "@/ui/PasswordForm";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -16,20 +16,11 @@ export default async function Page({
|
||||
}) {
|
||||
const { loginName, organization, promptPasswordless, authRequestId, alt } =
|
||||
searchParams;
|
||||
const sessionFactors = await loadSession(loginName, organization);
|
||||
|
||||
async function loadSession(loginName?: string, organization?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
}
|
||||
const sessionFactors = await loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
});
|
||||
|
||||
const branding = await getBrandingSettings(organization);
|
||||
const loginSettings = await getLoginSettings(organization);
|
||||
|
||||
@@ -51,6 +51,9 @@ export default async function Page({
|
||||
<RegisterFormWithoutPassword
|
||||
legal={legal}
|
||||
organization={organization}
|
||||
firstname={firstname}
|
||||
lastname={lastname}
|
||||
email={email}
|
||||
authRequestId={authRequestId}
|
||||
></RegisterFormWithoutPassword>
|
||||
)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { createCallback, getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { getMostRecentCookieWithLoginname } from "@zitadel/next";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
async function loadSession(loginName: string, authRequestId?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(`${loginName}`);
|
||||
const recent = await getMostRecentCookieWithLoginname({ loginName });
|
||||
|
||||
if (authRequestId) {
|
||||
return createCallback({
|
||||
|
||||
@@ -1,23 +1,14 @@
|
||||
import {
|
||||
getBrandingSettings,
|
||||
getLoginSettings,
|
||||
getSession,
|
||||
} from "@/lib/zitadel";
|
||||
import { getBrandingSettings, getSession, sessionService } from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import LoginPasskey from "@/ui/LoginPasskey";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import {
|
||||
getMostRecentCookieWithLoginname,
|
||||
getSessionCookieById,
|
||||
} from "@/utils/cookies";
|
||||
import { getSessionCookieById, loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
params,
|
||||
}: {
|
||||
searchParams: Record<string | number | symbol, string | undefined>;
|
||||
params: Record<string | number | symbol, string | undefined>;
|
||||
}) {
|
||||
const { loginName, authRequestId, sessionId, organization } = searchParams;
|
||||
|
||||
@@ -25,25 +16,10 @@ export default async function Page({
|
||||
|
||||
const sessionFactors = sessionId
|
||||
? await loadSessionById(sessionId, organization)
|
||||
: await loadSessionByLoginname(loginName, organization);
|
||||
|
||||
async function loadSessionByLoginname(
|
||||
loginName?: string,
|
||||
organization?: string,
|
||||
) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
}
|
||||
: await loadMostRecentSession(sessionService, { loginName, organization });
|
||||
|
||||
async function loadSessionById(sessionId: string, organization?: string) {
|
||||
const recent = await getSessionCookieById(sessionId, organization);
|
||||
const recent = await getSessionCookieById({ sessionId, organization });
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||
import Alert, { AlertType } from "@/ui/Alert";
|
||||
import { getBrandingSettings, sessionService } from "@/lib/zitadel";
|
||||
import Alert from "@/ui/Alert";
|
||||
import DynamicTheme from "@/ui/DynamicTheme";
|
||||
import RegisterPasskey from "@/ui/RegisterPasskey";
|
||||
import RegisterU2F from "@/ui/RegisterU2F";
|
||||
import UserAvatar from "@/ui/UserAvatar";
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
@@ -13,19 +12,11 @@ export default async function Page({
|
||||
}) {
|
||||
const { loginName, organization, authRequestId } = searchParams;
|
||||
|
||||
const sessionFactors = await loadSession(loginName);
|
||||
const sessionFactors = await loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
});
|
||||
|
||||
async function loadSession(loginName?: string) {
|
||||
const recent = await getMostRecentCookieWithLoginname(
|
||||
loginName,
|
||||
organization,
|
||||
);
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
if (response?.session) {
|
||||
return response.session;
|
||||
}
|
||||
});
|
||||
}
|
||||
const title = "Use your passkey to confirm it's really you";
|
||||
const description =
|
||||
"Your device will ask for your fingerprint, face, or screen lock";
|
||||
|
||||
@@ -4,16 +4,8 @@ import VerifyEmailForm from "@/ui/VerifyEmailForm";
|
||||
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
export default async function Page({ searchParams }: { searchParams: any }) {
|
||||
const {
|
||||
userId,
|
||||
sessionId,
|
||||
code,
|
||||
submit,
|
||||
organization,
|
||||
authRequestId,
|
||||
loginname,
|
||||
passwordset,
|
||||
} = searchParams;
|
||||
const { userId, sessionId, code, submit, organization, authRequestId } =
|
||||
searchParams;
|
||||
|
||||
const branding = await getBrandingSettings(organization);
|
||||
|
||||
|
||||
@@ -1,12 +1,20 @@
|
||||
import { listAuthenticationMethodTypes, listUsers } from "@/lib/zitadel";
|
||||
import { ProviderSlug } from "@/lib/demos";
|
||||
import {
|
||||
getActiveIdentityProviders,
|
||||
getLoginSettings,
|
||||
listAuthenticationMethodTypes,
|
||||
listUsers,
|
||||
startIdentityProviderFlow,
|
||||
} from "@/lib/zitadel";
|
||||
import { createSessionForUserIdAndUpdateCookie } from "@/utils/session";
|
||||
import { IdentityProviderType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const body = await request.json();
|
||||
if (body) {
|
||||
const { loginName, authRequestId, organization } = body;
|
||||
return listUsers(loginName, organization).then((users) => {
|
||||
return listUsers(loginName, organization).then(async (users) => {
|
||||
if (users.details?.totalResult == BigInt(1) && users.result[0].userId) {
|
||||
const userId = users.result[0].userId;
|
||||
return createSessionForUserIdAndUpdateCookie(
|
||||
@@ -37,6 +45,102 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json(error, { status: 500 });
|
||||
});
|
||||
} else {
|
||||
const loginSettings = await getLoginSettings(organization);
|
||||
// TODO: check if allowDomainDiscovery has to be allowed too, to redirect to the register page
|
||||
// user not found, check if register is enabled on organization
|
||||
|
||||
if (
|
||||
loginSettings?.allowRegister &&
|
||||
!loginSettings?.allowUsernamePassword
|
||||
) {
|
||||
// TODO redirect to loginname page with idp hint
|
||||
const identityProviders = await getActiveIdentityProviders(
|
||||
organization,
|
||||
).then((resp) => {
|
||||
return resp.identityProviders;
|
||||
});
|
||||
|
||||
if (identityProviders.length === 1) {
|
||||
const host = request.nextUrl.origin;
|
||||
|
||||
const identityProviderType = identityProviders[0].type;
|
||||
let provider: string;
|
||||
|
||||
switch (identityProviderType) {
|
||||
case IdentityProviderType.GITHUB:
|
||||
provider = "github";
|
||||
break;
|
||||
case IdentityProviderType.GOOGLE:
|
||||
provider = "google";
|
||||
break;
|
||||
case IdentityProviderType.AZURE_AD:
|
||||
provider = "azure";
|
||||
break;
|
||||
case IdentityProviderType.SAML:
|
||||
provider = "saml";
|
||||
break;
|
||||
case IdentityProviderType.OIDC:
|
||||
provider = "oidc";
|
||||
break;
|
||||
default:
|
||||
provider = "oidc";
|
||||
break;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (authRequestId) {
|
||||
params.set("authRequestId", authRequestId);
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
}
|
||||
|
||||
return startIdentityProviderFlow({
|
||||
idpId: identityProviders[0].id,
|
||||
urls: {
|
||||
successUrl:
|
||||
`${host}/idp/${provider}/success?` +
|
||||
new URLSearchParams(params),
|
||||
failureUrl:
|
||||
`${host}/idp/${provider}/failure?` +
|
||||
new URLSearchParams(params),
|
||||
},
|
||||
}).then((resp: any) => {
|
||||
if (resp.authUrl) {
|
||||
return NextResponse.json({ nextStep: resp.authUrl });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{ message: "Could not find user" },
|
||||
{ status: 404 },
|
||||
);
|
||||
}
|
||||
} else if (
|
||||
loginSettings?.allowRegister &&
|
||||
loginSettings?.allowUsernamePassword
|
||||
) {
|
||||
const params: any = { organization };
|
||||
if (authRequestId) {
|
||||
params.authRequestId = authRequestId;
|
||||
}
|
||||
if (loginName) {
|
||||
params.email = loginName;
|
||||
}
|
||||
|
||||
const registerUrl = new URL(
|
||||
"/register?" + new URLSearchParams(params),
|
||||
request.url,
|
||||
);
|
||||
|
||||
return NextResponse.json({
|
||||
nextStep: registerUrl,
|
||||
status: 200,
|
||||
});
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ message: "Could not find user" },
|
||||
{ status: 404 },
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import {
|
||||
SessionCookie,
|
||||
getMostRecentSessionCookie,
|
||||
getSessionCookieById,
|
||||
getSessionCookieByLoginName,
|
||||
} from "@/utils/cookies";
|
||||
} from "@zitadel/next";
|
||||
import { setSessionAndUpdateCookie } from "@/utils/session";
|
||||
import { NextRequest, NextResponse, userAgent } from "next/server";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client2";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const body = await request.json();
|
||||
@@ -16,12 +15,12 @@ export async function POST(request: NextRequest) {
|
||||
const { loginName, sessionId, organization, authRequestId, code, method } =
|
||||
body;
|
||||
|
||||
const recentPromise: Promise<SessionCookie> = sessionId
|
||||
? getSessionCookieById(sessionId).catch((error) => {
|
||||
const recentPromise = sessionId
|
||||
? getSessionCookieById({ sessionId }).catch((error) => {
|
||||
return Promise.reject(error);
|
||||
})
|
||||
: loginName
|
||||
? getSessionCookieByLoginName(loginName, organization).catch(
|
||||
? getSessionCookieByLoginName({ loginName, organization }).catch(
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
getSession,
|
||||
registerPasskey,
|
||||
} from "@/lib/zitadel";
|
||||
import { getSessionCookieById } from "@/utils/cookies";
|
||||
import { getSessionCookieById } from "@zitadel/next";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@@ -11,7 +11,7 @@ export async function POST(request: NextRequest) {
|
||||
if (body) {
|
||||
const { sessionId } = body;
|
||||
|
||||
const sessionCookie = await getSessionCookieById(sessionId);
|
||||
const sessionCookie = await getSessionCookieById({ sessionId });
|
||||
|
||||
const session = await getSession(sessionCookie.id, sessionCookie.token);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getSession, verifyPasskeyRegistration } from "@/lib/zitadel";
|
||||
import { getSessionCookieById } from "@/utils/cookies";
|
||||
import { getSessionCookieById } from "@zitadel/next";
|
||||
import { NextRequest, NextResponse, userAgent } from "next/server";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@@ -13,7 +13,7 @@ export async function POST(request: NextRequest) {
|
||||
device.vendor || device.model ? ", " : ""
|
||||
}${os.name}${os.name ? ", " : ""}${browser.name}`;
|
||||
}
|
||||
const sessionCookie = await getSessionCookieById(sessionId);
|
||||
const sessionCookie = await getSessionCookieById({ sessionId });
|
||||
|
||||
const session = await getSession(sessionCookie.id, sessionCookie.token);
|
||||
|
||||
|
||||
@@ -5,12 +5,11 @@ import {
|
||||
listAuthenticationMethodTypes,
|
||||
} from "@/lib/zitadel";
|
||||
import {
|
||||
SessionCookie,
|
||||
getMostRecentSessionCookie,
|
||||
getSessionCookieById,
|
||||
getSessionCookieByLoginName,
|
||||
removeSessionFromCookie,
|
||||
} from "@/utils/cookies";
|
||||
} from "@zitadel/next";
|
||||
import {
|
||||
createSessionAndUpdateCookie,
|
||||
createSessionForIdpAndUpdateCookie,
|
||||
@@ -76,12 +75,12 @@ export async function PUT(request: NextRequest) {
|
||||
challenges,
|
||||
} = body;
|
||||
|
||||
const recentPromise: Promise<SessionCookie> = sessionId
|
||||
const recentPromise = sessionId
|
||||
? getSessionCookieById(sessionId).catch((error) => {
|
||||
return Promise.reject(error);
|
||||
})
|
||||
: loginName
|
||||
? getSessionCookieByLoginName(loginName, organization).catch(
|
||||
? getSessionCookieByLoginName({ loginName, organization }).catch(
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
@@ -166,9 +165,9 @@ export async function PUT(request: NextRequest) {
|
||||
*/
|
||||
export async function DELETE(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const id = searchParams.get("id");
|
||||
if (id) {
|
||||
const session = await getSessionCookieById(id);
|
||||
const sessionId = searchParams.get("id");
|
||||
if (sessionId) {
|
||||
const session = await getSessionCookieById({ sessionId });
|
||||
|
||||
return deleteSession(session.id, session.token)
|
||||
.then(() => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
registerPasskey,
|
||||
registerU2F,
|
||||
} from "@/lib/zitadel";
|
||||
import { getSessionCookieById } from "@/utils/cookies";
|
||||
import { getSessionCookieById } from "@zitadel/next";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
@@ -12,7 +12,7 @@ export async function POST(request: NextRequest) {
|
||||
if (body) {
|
||||
const { sessionId } = body;
|
||||
|
||||
const sessionCookie = await getSessionCookieById(sessionId);
|
||||
const sessionCookie = await getSessionCookieById({ sessionId });
|
||||
|
||||
const session = await getSession(sessionCookie.id, sessionCookie.token);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { getSession, verifyU2FRegistration } from "@/lib/zitadel";
|
||||
import { getSessionCookieById } from "@/utils/cookies";
|
||||
import { getSessionCookieById } from "@zitadel/next";
|
||||
import { NextRequest, NextResponse, userAgent } from "next/server";
|
||||
import { VerifyU2FRegistrationRequest } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client2";
|
||||
import { VerifyU2FRegistrationRequest } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client";
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const body = await request.json();
|
||||
@@ -15,7 +15,7 @@ export async function POST(request: NextRequest) {
|
||||
device.vendor || device.model ? ", " : ""
|
||||
}${os.name}${os.name ? ", " : ""}${browser.name}`;
|
||||
}
|
||||
const sessionCookie = await getSessionCookieById(sessionId);
|
||||
const sessionCookie = await getSessionCookieById({ sessionId });
|
||||
|
||||
const session = await getSession(sessionCookie.id, sessionCookie.token);
|
||||
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
export const dynamic = "force-dynamic";
|
||||
export const revalidate = false;
|
||||
export const fetchCache = "default-no-store";
|
||||
|
||||
import {
|
||||
createCallback,
|
||||
getActiveIdentityProviders,
|
||||
getAuthRequest,
|
||||
getOrgByDomain,
|
||||
listSessions,
|
||||
startIdentityProviderFlow,
|
||||
} from "@/lib/zitadel";
|
||||
import { SessionCookie, getAllSessions } from "@/utils/cookies";
|
||||
import { getAllSessions } from "@zitadel/next";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2beta/session_pb";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
import {
|
||||
AuthRequest,
|
||||
Prompt,
|
||||
} from "@zitadel/proto/zitadel/oidc/v2beta/authorization_pb";
|
||||
} from "@zitadel/proto/zitadel/oidc/v2/authorization_pb";
|
||||
import { IdentityProviderType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
|
||||
async function loadSessions(ids: string[]): Promise<Session[]> {
|
||||
const response = await listSessions(
|
||||
@@ -22,6 +29,7 @@ async function loadSessions(ids: string[]): Promise<Session[]> {
|
||||
|
||||
const ORG_SCOPE_REGEX = /urn:zitadel:iam:org:id:([0-9]+)/;
|
||||
const ORG_DOMAIN_SCOPE_REGEX = /urn:zitadel:iam:org:domain:primary:(.+)/; // TODO: check regex for all domain character options
|
||||
const IDP_SCOPE_REGEX = /urn:zitadel:iam:org:idp:id:(.+)/;
|
||||
|
||||
function findSession(
|
||||
sessions: Session[],
|
||||
@@ -48,7 +56,13 @@ export async function GET(request: NextRequest) {
|
||||
const authRequestId = searchParams.get("authRequest");
|
||||
const sessionId = searchParams.get("sessionId");
|
||||
|
||||
const sessionCookies: SessionCookie[] = await getAllSessions();
|
||||
// TODO: find a better way to handle _rsc (react server components) requests and block them to avoid conflicts when creating oidc callback
|
||||
const _rsc = searchParams.get("_rsc");
|
||||
if (_rsc) {
|
||||
return NextResponse.json({ error: "No _rsc supported" }, { status: 500 });
|
||||
}
|
||||
|
||||
const sessionCookies = await getAllSessions();
|
||||
const ids = sessionCookies.map((s) => s.id);
|
||||
let sessions: Session[] = [];
|
||||
if (ids && ids.length) {
|
||||
@@ -76,36 +90,50 @@ export async function GET(request: NextRequest) {
|
||||
);
|
||||
|
||||
if (cookie && cookie.id && cookie.token) {
|
||||
console.log(`Found sessioncookie ${cookie.id}`);
|
||||
|
||||
const session = {
|
||||
sessionId: cookie?.id,
|
||||
sessionToken: cookie?.token,
|
||||
};
|
||||
|
||||
const { callbackUrl } = await createCallback({
|
||||
authRequestId,
|
||||
callbackKind: {
|
||||
case: "session",
|
||||
value: session,
|
||||
},
|
||||
});
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
// works not with _rsc request
|
||||
try {
|
||||
const { callbackUrl } = await createCallback({
|
||||
authRequestId,
|
||||
callbackKind: {
|
||||
case: "session",
|
||||
value: session,
|
||||
},
|
||||
});
|
||||
if (callbackUrl) {
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
return NextResponse.json(
|
||||
{ error: "An error occurred!" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
return NextResponse.json({ error }, { status: 500 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (authRequestId) {
|
||||
console.log(`Login with authRequest: ${authRequestId}`);
|
||||
const { authRequest } = await getAuthRequest({ authRequestId });
|
||||
|
||||
let organization = "";
|
||||
let idpId = "";
|
||||
|
||||
if (authRequest?.scope) {
|
||||
const orgScope = authRequest.scope.find((s: string) =>
|
||||
ORG_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
const idpScope = authRequest.scope.find((s: string) =>
|
||||
IDP_SCOPE_REGEX.test(s),
|
||||
);
|
||||
|
||||
if (orgScope) {
|
||||
const matched = ORG_SCOPE_REGEX.exec(orgScope);
|
||||
organization = matched?.[1] ?? "";
|
||||
@@ -123,6 +151,76 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (idpScope) {
|
||||
const matched = IDP_SCOPE_REGEX.exec(idpScope);
|
||||
idpId = matched?.[1] ?? "";
|
||||
|
||||
const identityProviders = await getActiveIdentityProviders(
|
||||
organization ? organization : undefined,
|
||||
).then((resp) => {
|
||||
return resp.identityProviders;
|
||||
});
|
||||
|
||||
const idp = identityProviders.find((idp) => idp.id === idpId);
|
||||
|
||||
if (idp) {
|
||||
const host = request.nextUrl.origin;
|
||||
|
||||
const identityProviderType = identityProviders[0].type;
|
||||
let provider: string;
|
||||
|
||||
switch (identityProviderType) {
|
||||
case IdentityProviderType.GITHUB:
|
||||
provider = "github";
|
||||
break;
|
||||
case IdentityProviderType.GOOGLE:
|
||||
provider = "google";
|
||||
break;
|
||||
case IdentityProviderType.AZURE_AD:
|
||||
provider = "azure";
|
||||
break;
|
||||
case IdentityProviderType.SAML:
|
||||
provider = "saml";
|
||||
break;
|
||||
case IdentityProviderType.OIDC:
|
||||
provider = "oidc";
|
||||
break;
|
||||
default:
|
||||
provider = "oidc";
|
||||
break;
|
||||
}
|
||||
|
||||
const params = new URLSearchParams();
|
||||
|
||||
if (authRequestId) {
|
||||
params.set("authRequestId", authRequestId);
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
params.set("organization", organization);
|
||||
}
|
||||
|
||||
return startIdentityProviderFlow({
|
||||
idpId,
|
||||
urls: {
|
||||
successUrl:
|
||||
`${host}/idp/${provider}/success?` +
|
||||
new URLSearchParams(params),
|
||||
failureUrl:
|
||||
`${host}/idp/${provider}/failure?` +
|
||||
new URLSearchParams(params),
|
||||
},
|
||||
}).then((resp) => {
|
||||
if (
|
||||
resp.nextStep.value &&
|
||||
typeof resp.nextStep.value === "string"
|
||||
) {
|
||||
return NextResponse.redirect(resp.nextStep.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const gotoAccounts = (): NextResponse<unknown> => {
|
||||
@@ -227,6 +325,9 @@ export async function GET(request: NextRequest) {
|
||||
if (callbackUrl) {
|
||||
return NextResponse.redirect(callbackUrl);
|
||||
} else {
|
||||
console.log(
|
||||
"could not create callback, redirect user to choose other account",
|
||||
);
|
||||
return gotoAccounts();
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,54 +1,8 @@
|
||||
import { demos } from "@/lib/demos";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function Page() {
|
||||
return (
|
||||
<div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20 mb-10">
|
||||
<div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500 px-8 py-12">
|
||||
<div className="space-y-8">
|
||||
<h1 className="text-xl font-medium">Pages</h1>
|
||||
|
||||
<div className="space-y-10">
|
||||
{demos.map((section) => {
|
||||
return (
|
||||
<div key={section.name} className="space-y-5">
|
||||
<div className="text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||
{section.name}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-5 lg:grid-cols-2">
|
||||
{section.items.map((item) => {
|
||||
return (
|
||||
<Link
|
||||
href={`/${item.slug}`}
|
||||
key={item.name}
|
||||
className="bg-background-light-400 dark:bg-background-dark-400 group block space-y-1.5 rounded-md px-5 py-3 hover:shadow-lg hover:dark:bg-white/10 border border-divider-light dark:border-divider-dark transition-all "
|
||||
>
|
||||
<div className="font-medium">{item.name}</div>
|
||||
|
||||
{item.description ? (
|
||||
<div className="line-clamp-3 text-sm text-text-light-secondary-500 dark:text-text-dark-secondary-500">
|
||||
{item.description}
|
||||
</div>
|
||||
) : null}
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<div className="mb-5 text-xs font-semibold uppercase tracking-wider text-gray-500">
|
||||
Deploy your own on Vercel
|
||||
</div>
|
||||
<a href="https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fzitadel%2Ftypescript&root-directory=apps/login&env=ZITADEL_API_URL,ZITADEL_SERVICE_USER_ID,ZITADEL_SERVICE_USER_TOKEN&envDescription=Setup%20a%20service%20account%20with%20IAM_OWNER%20membership%20on%20your%20instance%20and%20provide%20its%20id%20and%20personal%20access%20token.&project-name=zitadel-login&repository-name=zitadel-login">
|
||||
<img src="https://vercel.com/button" alt="Deploy with Vercel" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
// automatically redirect to loginname
|
||||
if (process.env.DEBUG !== "true") {
|
||||
redirect("/loginname");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { listSessions } from "@/lib/zitadel";
|
||||
import { SessionCookie, getAllSessions } from "@/utils/cookies";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2beta/session_pb";
|
||||
import { getAllSessions } from "@zitadel/next";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
|
||||
async function loadSessions(ids: string[]): Promise<Session[]> {
|
||||
@@ -12,7 +12,7 @@ async function loadSessions(ids: string[]): Promise<Session[]> {
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
const sessionCookies: SessionCookie[] = await getAllSessions();
|
||||
const sessionCookies = await getAllSessions();
|
||||
const ids = sessionCookies.map((s) => s.id);
|
||||
let sessions: Session[] = [];
|
||||
if (ids && ids.length) {
|
||||
|
||||
@@ -7,6 +7,7 @@ export type Item = {
|
||||
export enum ProviderSlug {
|
||||
GOOGLE = "google",
|
||||
GITHUB = "github",
|
||||
AZURE = "microsoft",
|
||||
}
|
||||
|
||||
export const demos: { name: string; items: Item[] }[] = [
|
||||
|
||||
@@ -1,24 +1,21 @@
|
||||
"use server";
|
||||
|
||||
import { getMostRecentCookieWithLoginname } from "@/utils/cookies";
|
||||
import { getSession, verifyTOTPRegistration } from "./zitadel";
|
||||
import { loadMostRecentSession } from "@zitadel/next";
|
||||
import { sessionService, verifyTOTPRegistration } from "./zitadel";
|
||||
|
||||
export async function verifyTOTP(
|
||||
code: string,
|
||||
loginName?: string,
|
||||
organization?: string,
|
||||
) {
|
||||
return getMostRecentCookieWithLoginname(loginName, organization)
|
||||
.then((recent) => {
|
||||
return getSession(recent.id, recent.token).then((response) => {
|
||||
return { session: response?.session, token: recent.token };
|
||||
});
|
||||
})
|
||||
.then(({ session, token }) => {
|
||||
if (session?.factors?.user?.id) {
|
||||
return verifyTOTPRegistration(code, session.factors.user.id, token);
|
||||
} else {
|
||||
throw Error("No user id found in session.");
|
||||
}
|
||||
});
|
||||
return loadMostRecentSession(sessionService, {
|
||||
loginName,
|
||||
organization,
|
||||
}).then((session) => {
|
||||
if (session?.factors?.user?.id) {
|
||||
return verifyTOTPRegistration(code, session.factors.user.id);
|
||||
} else {
|
||||
throw Error("No user id found in session.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,26 +4,21 @@ import {
|
||||
createSettingsServiceClient,
|
||||
createUserServiceClient,
|
||||
makeReqCtx,
|
||||
} from "@zitadel/client2/v2beta";
|
||||
import { createManagementServiceClient } from "@zitadel/client2/v1";
|
||||
} from "@zitadel/client/v2";
|
||||
import { createManagementServiceClient } from "@zitadel/client/v1";
|
||||
import { createServerTransport } from "@zitadel/node";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { RequestChallenges } from "@zitadel/proto/zitadel/session/v2beta/challenge_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { RequestChallenges } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
import {
|
||||
RetrieveIdentityProviderIntentRequest,
|
||||
VerifyU2FRegistrationRequest,
|
||||
} from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { CreateCallbackRequest } from "@zitadel/proto/zitadel/oidc/v2beta/oidc_service_pb";
|
||||
import { TextQueryMethod } from "@zitadel/proto/zitadel/object/v2beta/object_pb";
|
||||
import type { RedirectURLs } from "@zitadel/proto/zitadel/user/v2beta/idp_pb";
|
||||
import { PlainMessage } from "@zitadel/client2";
|
||||
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
import { CreateCallbackRequest } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb";
|
||||
import { TextQueryMethod } from "@zitadel/proto/zitadel/object/v2/object_pb";
|
||||
import type { RedirectURLs } from "@zitadel/proto/zitadel/user/v2/idp_pb";
|
||||
import { ProviderSlug } from "./demos";
|
||||
import { AddHumanUserRequest } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import {
|
||||
IDPInformation,
|
||||
IDPLink,
|
||||
} from "@zitadel/proto/zitadel/user/v2beta/idp_pb";
|
||||
import { PartialMessage } from "@zitadel/client2";
|
||||
import { PlainMessage } from "@zitadel/client";
|
||||
|
||||
const SESSION_LIFETIME_S = 3000;
|
||||
|
||||
@@ -230,24 +225,7 @@ export async function addHumanUser({
|
||||
});
|
||||
}
|
||||
|
||||
export async function verifyTOTPRegistration(
|
||||
code: string,
|
||||
userId: string,
|
||||
token?: string,
|
||||
) {
|
||||
// let userService;
|
||||
// if (token) {
|
||||
// const authConfig: ZitadelServerOptions = {
|
||||
// name: "zitadel login",
|
||||
// apiUrl: process.env.ZITADEL_API_URL ?? "",
|
||||
// token: token,
|
||||
// };
|
||||
//
|
||||
// const sessionUser = initializeServer(authConfig);
|
||||
// userService = user.getUser(sessionUser);
|
||||
// } else {
|
||||
// userService = user.getUser(server);
|
||||
// }
|
||||
export async function verifyTOTPRegistration(code: string, userId: string) {
|
||||
return userService.verifyTOTPRegistration({ code, userId }, {});
|
||||
}
|
||||
|
||||
@@ -298,6 +276,14 @@ export async function getOrgByDomain(domain: string) {
|
||||
return managementService.getOrgByDomainGlobal({ domain }, {});
|
||||
}
|
||||
|
||||
export const PROVIDER_NAME_MAPPING: {
|
||||
[provider: string]: string;
|
||||
} = {
|
||||
[ProviderSlug.GOOGLE]: "Google",
|
||||
[ProviderSlug.GITHUB]: "GitHub",
|
||||
[ProviderSlug.AZURE]: "Microft",
|
||||
};
|
||||
|
||||
export async function startIdentityProviderFlow({
|
||||
idpId,
|
||||
urls,
|
||||
@@ -535,6 +521,13 @@ export async function verifyU2FRegistration(
|
||||
return userService.verifyU2FRegistration(request, {});
|
||||
}
|
||||
|
||||
export async function getActiveIdentityProviders(orgId?: string) {
|
||||
return settingsService.getActiveIdentityProviders(
|
||||
{ ctx: makeReqCtx(orgId) },
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param userId the id of the user where the email should be set
|
||||
|
||||
@@ -19,6 +19,10 @@ export function middleware(request: NextRequest) {
|
||||
|
||||
// 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}`);
|
||||
|
||||
// this is a workaround for the next.js server not forwarding the host header
|
||||
// requestHeaders.set("x-zitadel-instance-host", `${INSTANCE}`);
|
||||
|
||||
const responseHeaders = new Headers();
|
||||
responseHeaders.set("Access-Control-Allow-Origin", "*");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { ColorShade, getColorHash } from "@/utils/colors";
|
||||
import { useTheme } from "next-themes";
|
||||
import Image from "next/image";
|
||||
|
||||
interface AvatarProps {
|
||||
name: string | null | undefined;
|
||||
@@ -71,14 +72,17 @@ export function Avatar({
|
||||
: size === "base"
|
||||
? "w-[38px] h-[38px] font-bold"
|
||||
: size === "small"
|
||||
? "w-[32px] h-[32px] font-bold text-[13px]"
|
||||
: ""
|
||||
? "!w-[32px] !h-[32px] font-bold text-[13px]"
|
||||
: "w-12 h-12"
|
||||
}`}
|
||||
style={resolvedTheme === "light" ? avatarStyleLight : avatarStyleDark}
|
||||
>
|
||||
{imageUrl ? (
|
||||
<img
|
||||
className="border border-divider-light dark:border-divider-dark rounded-full w-12 h-12"
|
||||
<Image
|
||||
height={48}
|
||||
width={48}
|
||||
alt="avatar"
|
||||
className="w-full h-full border border-divider-light dark:border-divider-dark rounded-full"
|
||||
src={imageUrl}
|
||||
/>
|
||||
) : (
|
||||
|
||||
@@ -5,7 +5,7 @@ import { BadgeState, StateBadge } from "./StateBadge";
|
||||
import clsx from "clsx";
|
||||
import { CheckIcon } from "@heroicons/react/24/outline";
|
||||
import { EMAIL, SMS, TOTP, U2F } from "./AuthMethods";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
type Props = {
|
||||
loginName?: string;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { EMAIL, SMS, TOTP, U2F } from "./AuthMethods";
|
||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2beta/login_settings_pb";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
type Props = {
|
||||
loginName?: string;
|
||||
|
||||
@@ -4,7 +4,7 @@ import React from "react";
|
||||
import { Logo } from "@/ui/Logo";
|
||||
import ThemeWrapper from "./ThemeWrapper";
|
||||
import { LayoutProviders } from "./LayoutProviders";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2beta/branding_settings_pb";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||
|
||||
export default function DynamicTheme({
|
||||
branding,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { ZitadelReactProvider } from "@zitadel/react";
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import { Spinner } from "./Spinner";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { TextInput } from "./Input";
|
||||
import BackButton from "./BackButton";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client2";
|
||||
import { Challenges } from "@zitadel/proto/zitadel/session/v2beta/challenge_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client";
|
||||
import { Challenges } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
|
||||
// either loginName or sessionId must be provided
|
||||
type Props = {
|
||||
@@ -236,7 +236,9 @@ export default function LoginOTP({
|
||||
className="self-end"
|
||||
variant={ButtonVariants.Primary}
|
||||
disabled={loading || !formState.isValid}
|
||||
onClick={handleSubmit((e) => setCodeAndContinue(e, organization))}
|
||||
onClick={handleSubmit((e) => {
|
||||
setCodeAndContinue(e, organization);
|
||||
})}
|
||||
>
|
||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||
continue
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Button, ButtonVariants } from "./Button";
|
||||
import Alert from "./Alert";
|
||||
import { Spinner } from "./Spinner";
|
||||
import BackButton from "./BackButton";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
|
||||
// either loginName or sessionId must be provided
|
||||
type Props = {
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
symbolValidator,
|
||||
upperCaseValidator,
|
||||
} from "@/utils/validators";
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2beta/password_settings_pb";
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||
|
||||
type Props = {
|
||||
passwordComplexitySettings: PasswordComplexitySettings;
|
||||
|
||||
@@ -8,9 +8,9 @@ import { useRouter } from "next/navigation";
|
||||
import { Spinner } from "./Spinner";
|
||||
import Alert from "./Alert";
|
||||
import BackButton from "./BackButton";
|
||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2beta/login_settings_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
type Inputs = {
|
||||
password: string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { Checkbox } from "./Checkbox";
|
||||
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2beta/legal_settings_pb";
|
||||
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb";
|
||||
|
||||
type Props = {
|
||||
legal: LegalAndSupportSettings;
|
||||
|
||||
@@ -12,7 +12,8 @@ import AuthenticationMethodRadio, {
|
||||
} from "./AuthenticationMethodRadio";
|
||||
import Alert from "./Alert";
|
||||
import BackButton from "./BackButton";
|
||||
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2beta/legal_settings_pb";
|
||||
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb";
|
||||
import { first } from "node_modules/cypress/types/lodash";
|
||||
|
||||
type Inputs =
|
||||
| {
|
||||
@@ -24,17 +25,28 @@ type Inputs =
|
||||
|
||||
type Props = {
|
||||
legal: LegalAndSupportSettings;
|
||||
firstname?: string;
|
||||
lastname?: string;
|
||||
email?: string;
|
||||
organization?: string;
|
||||
authRequestId?: string;
|
||||
};
|
||||
|
||||
export default function RegisterFormWithoutPassword({
|
||||
legal,
|
||||
email,
|
||||
firstname,
|
||||
lastname,
|
||||
organization,
|
||||
authRequestId,
|
||||
}: Props) {
|
||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||
mode: "onBlur",
|
||||
defaultValues: {
|
||||
email: email ?? "",
|
||||
firstName: firstname ?? "",
|
||||
lastname: lastname ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Spinner } from "./Spinner";
|
||||
import Alert from "./Alert";
|
||||
import { coerceToArrayBuffer, coerceToBase64Url } from "@/utils/base64";
|
||||
import BackButton from "./BackButton";
|
||||
import { RegisterPasskeyResponse } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { RegisterPasskeyResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
type Inputs = {};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Spinner } from "./Spinner";
|
||||
import Alert from "./Alert";
|
||||
import { coerceToArrayBuffer, coerceToBase64Url } from "@/utils/base64";
|
||||
import BackButton from "./BackButton";
|
||||
import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2beta/user_service_pb";
|
||||
import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||
|
||||
type Inputs = {};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useState } from "react";
|
||||
import { Avatar } from "./Avatar";
|
||||
import moment from "moment";
|
||||
import { XCircleIcon } from "@heroicons/react/24/outline";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2beta/session_pb";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
|
||||
export default function SessionItem({
|
||||
session,
|
||||
@@ -54,33 +54,40 @@ export default function SessionItem({
|
||||
|
||||
return (
|
||||
<Link
|
||||
prefetch={false}
|
||||
href={
|
||||
validUser
|
||||
validUser && authRequestId
|
||||
? `/login?` +
|
||||
new URLSearchParams(
|
||||
authRequestId
|
||||
? {
|
||||
// loginName: session.factors?.user?.loginName as string,
|
||||
sessionId: session.id,
|
||||
authRequest: authRequestId,
|
||||
}
|
||||
: {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
},
|
||||
)
|
||||
: `/loginname?` +
|
||||
new URLSearchParams(
|
||||
authRequestId
|
||||
? {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
submit: "true",
|
||||
authRequestId,
|
||||
}
|
||||
: {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
submit: "true",
|
||||
},
|
||||
)
|
||||
new URLSearchParams({
|
||||
// loginName: session.factors?.user?.loginName as string,
|
||||
sessionId: session.id,
|
||||
authRequest: authRequestId,
|
||||
})
|
||||
: !validUser
|
||||
? `/loginname?` +
|
||||
new URLSearchParams(
|
||||
authRequestId
|
||||
? {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
submit: "true",
|
||||
authRequestId,
|
||||
}
|
||||
: {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
submit: "true",
|
||||
},
|
||||
)
|
||||
: "/signedin?" +
|
||||
new URLSearchParams(
|
||||
authRequestId
|
||||
? {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
authRequestId,
|
||||
}
|
||||
: {
|
||||
loginName: session.factors?.user?.loginName as string,
|
||||
},
|
||||
)
|
||||
}
|
||||
className="group flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light hover:shadow-lg dark:hover:bg-white/10 py-2 px-4 rounded-md transition-all"
|
||||
>
|
||||
@@ -114,12 +121,11 @@ export default function SessionItem({
|
||||
|
||||
<XCircleIcon
|
||||
className="hidden group-hover:block h-5 w-5 transition-all opacity-50 hover:opacity-100"
|
||||
onClick={(event) => {
|
||||
event.preventDefault();
|
||||
onClick={() =>
|
||||
clearSession(session.id).then(() => {
|
||||
reload();
|
||||
});
|
||||
}}
|
||||
})
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import SessionItem from "./SessionItem";
|
||||
import Alert from "./Alert";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2beta/session_pb";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
|
||||
type Props = {
|
||||
sessions: Session[];
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Spinner } from "./Spinner";
|
||||
import Alert from "./Alert";
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2beta/password_settings_pb";
|
||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||
|
||||
type Inputs =
|
||||
| {
|
||||
@@ -42,6 +42,11 @@ export default function SetPasswordForm({
|
||||
}: Props) {
|
||||
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
||||
mode: "onBlur",
|
||||
defaultValues: {
|
||||
email: email ?? "",
|
||||
firstname: firstname ?? "",
|
||||
lastname: lastname ?? "",
|
||||
},
|
||||
});
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { useRouter } from "next/navigation";
|
||||
import { ProviderSlug } from "@/lib/demos";
|
||||
import Alert from "./Alert";
|
||||
import BackButton from "./BackButton";
|
||||
import { IdentityProvider } from "@zitadel/proto/zitadel/settings/v2beta/login_settings_pb";
|
||||
import { IdentityProvider } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
|
||||
export interface SignInWithIDPProps {
|
||||
children?: ReactNode;
|
||||
@@ -19,18 +19,13 @@ export interface SignInWithIDPProps {
|
||||
identityProviders: IdentityProvider[];
|
||||
authRequestId?: string;
|
||||
organization?: string;
|
||||
startIDPFlowPath?: (idpId: string) => string;
|
||||
}
|
||||
|
||||
const START_IDP_FLOW_PATH = (idpId: string) =>
|
||||
`/v2beta/users/idps/${idpId}/start`;
|
||||
|
||||
export function SignInWithIDP({
|
||||
host,
|
||||
identityProviders,
|
||||
authRequestId,
|
||||
organization,
|
||||
startIDPFlowPath = START_IDP_FLOW_PATH,
|
||||
}: SignInWithIDPProps) {
|
||||
// TODO: remove casting when bufbuild/protobuf-es@v2 is released
|
||||
identityProviders = identityProviders.map((idp) =>
|
||||
@@ -107,7 +102,13 @@ export function SignInWithIDP({
|
||||
return (
|
||||
<SignInWithAzureAD
|
||||
key={`idp-${i}`}
|
||||
onClick={() => alert("TODO: unimplemented")}
|
||||
onClick={() =>
|
||||
startFlow(idp.id, ProviderSlug.AZURE).then(
|
||||
({ authUrl }) => {
|
||||
router.push(authUrl);
|
||||
},
|
||||
)
|
||||
}
|
||||
></SignInWithAzureAD>
|
||||
);
|
||||
case 10: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_GOOGLE:
|
||||
@@ -148,10 +149,6 @@ export function SignInWithIDP({
|
||||
<Alert>{error}</Alert>
|
||||
</div>
|
||||
)}
|
||||
<div className="mt-8 flex w-full flex-row items-center pt-4">
|
||||
<BackButton />
|
||||
<span className="flex-grow"></span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import { setTheme } from "@/utils/colors";
|
||||
import { useEffect } from "react";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2beta/branding_settings_pb";
|
||||
import { PartialMessage } from "@zitadel/client2";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||
import { PartialMessage } from "@zitadel/client";
|
||||
|
||||
type Props = {
|
||||
branding: PartialMessage<BrandingSettings> | undefined;
|
||||
|
||||
@@ -10,7 +10,8 @@ import Alert from "./Alert";
|
||||
import {
|
||||
LoginSettings,
|
||||
PasskeysType,
|
||||
} from "@zitadel/proto/zitadel/settings/v2beta/login_settings_pb";
|
||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||
import BackButton from "./BackButton";
|
||||
|
||||
type Inputs = {
|
||||
loginName: string;
|
||||
@@ -23,6 +24,7 @@ type Props = {
|
||||
organization?: string;
|
||||
submit: boolean;
|
||||
allowRegister: boolean;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function UsernameForm({
|
||||
@@ -32,6 +34,7 @@ export default function UsernameForm({
|
||||
organization,
|
||||
submit,
|
||||
allowRegister,
|
||||
children,
|
||||
}: Props) {
|
||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||
mode: "onBlur",
|
||||
@@ -82,9 +85,10 @@ export default function UsernameForm({
|
||||
values: Inputs,
|
||||
organization?: string,
|
||||
) {
|
||||
console.log(loginSettings);
|
||||
return submitLoginName(values, organization).then((response) => {
|
||||
if (response.authMethodTypes.length == 1) {
|
||||
if (response.nextStep) {
|
||||
return router.push(response.nextStep);
|
||||
} else if (response.authMethodTypes.length == 1) {
|
||||
const method = response.authMethodTypes[0];
|
||||
switch (method) {
|
||||
case 1: // user has only password as auth method
|
||||
@@ -92,8 +96,11 @@ export default function UsernameForm({
|
||||
loginName: response.factors.user.loginName,
|
||||
};
|
||||
|
||||
if (organization) {
|
||||
paramsPassword.organization = organization;
|
||||
// TODO: does this have to be checked in loginSettings.allowDomainDiscovery
|
||||
|
||||
if (organization || response.factors.user.organizationId) {
|
||||
paramsPassword.organization =
|
||||
organization ?? response.factors.user.organizationId;
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -117,8 +124,10 @@ export default function UsernameForm({
|
||||
if (authRequestId) {
|
||||
paramsPasskey.authRequestId = authRequestId;
|
||||
}
|
||||
if (organization) {
|
||||
paramsPasskey.organization = organization;
|
||||
|
||||
if (organization || response.factors.user.organizationId) {
|
||||
paramsPasskey.organization =
|
||||
organization ?? response.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return router.push(
|
||||
@@ -134,8 +143,10 @@ export default function UsernameForm({
|
||||
if (authRequestId) {
|
||||
paramsPasskeyDefault.authRequestId = authRequestId;
|
||||
}
|
||||
if (organization) {
|
||||
paramsPasskeyDefault.organization = organization;
|
||||
|
||||
if (organization || response.factors.user.organizationId) {
|
||||
paramsPasskeyDefault.organization =
|
||||
organization ?? response.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return router.push(
|
||||
@@ -161,8 +172,9 @@ export default function UsernameForm({
|
||||
passkeyParams.authRequestId = authRequestId;
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
passkeyParams.organization = organization;
|
||||
if (organization || response.factors.user.organizationId) {
|
||||
passkeyParams.organization =
|
||||
organization ?? response.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return router.push(
|
||||
@@ -180,8 +192,9 @@ export default function UsernameForm({
|
||||
paramsPasswordDefault.authRequestId = authRequestId;
|
||||
}
|
||||
|
||||
if (organization) {
|
||||
paramsPasswordDefault.organization = organization;
|
||||
if (organization || response.factors.user.organizationId) {
|
||||
paramsPasswordDefault.organization =
|
||||
organization ?? response.factors.user.organizationId;
|
||||
}
|
||||
|
||||
return router.push(
|
||||
@@ -210,6 +223,16 @@ export default function UsernameForm({
|
||||
{...register("loginName", { required: "This field is required" })}
|
||||
label="Loginname"
|
||||
/>
|
||||
{allowRegister && (
|
||||
<button
|
||||
className="transition-all text-sm hover:text-primary-light-500 dark:hover:text-primary-dark-500"
|
||||
onClick={() => router.push("/register")}
|
||||
type="button"
|
||||
disabled={loading}
|
||||
>
|
||||
Register new user
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
@@ -218,17 +241,10 @@ export default function UsernameForm({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-8 flex w-full flex-row items-center">
|
||||
{allowRegister && (
|
||||
<Button
|
||||
type="button"
|
||||
className="self-end"
|
||||
variant={ButtonVariants.Secondary}
|
||||
onClick={() => router.push("/register")}
|
||||
>
|
||||
register
|
||||
</Button>
|
||||
)}
|
||||
<div className="pt-6 pb-4">{children}</div>
|
||||
|
||||
<div className="mt-4 flex w-full flex-row items-center">
|
||||
<BackButton />
|
||||
<span className="flex-grow"></span>
|
||||
<Button
|
||||
type="submit"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import tinycolor from "tinycolor2";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2beta/branding_settings_pb";
|
||||
import { PartialMessage } from "@zitadel/client2";
|
||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||
import { PartialMessage } from "@zitadel/client";
|
||||
|
||||
export interface Color {
|
||||
name: string;
|
||||
|
||||
@@ -6,18 +6,25 @@ import {
|
||||
getSession,
|
||||
setSession,
|
||||
} from "@/lib/zitadel";
|
||||
import {
|
||||
SessionCookie,
|
||||
addSessionToCookie,
|
||||
updateSessionCookie,
|
||||
} from "./cookies";
|
||||
import { addSessionToCookie, updateSessionCookie } from "@zitadel/next";
|
||||
import {
|
||||
Challenges,
|
||||
RequestChallenges,
|
||||
} from "@zitadel/proto/zitadel/session/v2beta/challenge_pb";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2beta/session_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2beta/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client2";
|
||||
} from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||
import { PlainMessage } from "@zitadel/client";
|
||||
|
||||
type CustomCookieData = {
|
||||
id: string;
|
||||
token: string;
|
||||
loginName: string;
|
||||
organization?: string;
|
||||
creationDate: string;
|
||||
expirationDate: string;
|
||||
changeDate: string;
|
||||
authRequestId?: string; // if its linked to an OIDC flow
|
||||
};
|
||||
|
||||
export async function createSessionAndUpdateCookie(
|
||||
loginName: string,
|
||||
@@ -43,7 +50,7 @@ export async function createSessionAndUpdateCookie(
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: SessionCookie = {
|
||||
const sessionCookie: any = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
@@ -61,7 +68,7 @@ export async function createSessionAndUpdateCookie(
|
||||
sessionCookie.organization = organization;
|
||||
}
|
||||
|
||||
return addSessionToCookie(sessionCookie).then(() => {
|
||||
return addSessionToCookie<CustomCookieData>(sessionCookie).then(() => {
|
||||
return response.session as Session;
|
||||
});
|
||||
} else {
|
||||
@@ -91,13 +98,12 @@ export async function createSessionForUserIdAndUpdateCookie(
|
||||
);
|
||||
|
||||
if (createdSession) {
|
||||
console.log("cs", createdSession);
|
||||
return getSession(
|
||||
createdSession.sessionId,
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: SessionCookie = {
|
||||
const sessionCookie: any = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
@@ -147,7 +153,7 @@ export async function createSessionForIdpAndUpdateCookie(
|
||||
createdSession.sessionToken,
|
||||
).then((response) => {
|
||||
if (response?.session && response.session?.factors?.user?.loginName) {
|
||||
const sessionCookie: SessionCookie = {
|
||||
const sessionCookie: any = {
|
||||
id: createdSession.sessionId,
|
||||
token: createdSession.sessionToken,
|
||||
creationDate: `${response.session.creationDate?.toDate().getTime() ?? ""}`,
|
||||
@@ -182,7 +188,7 @@ export type SessionWithChallenges = Session & {
|
||||
};
|
||||
|
||||
export async function setSessionAndUpdateCookie(
|
||||
recentCookie: SessionCookie,
|
||||
recentCookie: CustomCookieData,
|
||||
checks: PlainMessage<Checks>,
|
||||
challenges: RequestChallenges | undefined,
|
||||
authRequestId: string | undefined,
|
||||
@@ -194,7 +200,7 @@ export async function setSessionAndUpdateCookie(
|
||||
checks,
|
||||
).then((updatedSession) => {
|
||||
if (updatedSession) {
|
||||
const sessionCookie: SessionCookie = {
|
||||
const sessionCookie: CustomCookieData = {
|
||||
id: recentCookie.id,
|
||||
token: updatedSession.sessionToken,
|
||||
creationDate: recentCookie.creationDate,
|
||||
@@ -212,7 +218,7 @@ export async function setSessionAndUpdateCookie(
|
||||
(response) => {
|
||||
if (response?.session && response.session.factors?.user?.loginName) {
|
||||
const { session } = response;
|
||||
const newCookie: SessionCookie = {
|
||||
const newCookie: CustomCookieData = {
|
||||
id: sessionCookie.id,
|
||||
token: updatedSession.sessionToken,
|
||||
creationDate: sessionCookie.creationDate,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const sharedConfig = require("zitadel-tailwind-config/tailwind.config.js");
|
||||
const sharedConfig = require("zitadel-tailwind-config/tailwind.config.mjs");
|
||||
|
||||
let colors = {
|
||||
background: { light: { contrast: {} }, dark: { contrast: {} } },
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"pipeline": {
|
||||
"tasks": {
|
||||
"build": {
|
||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
||||
"dependsOn": ["^build"]
|
||||
@@ -8,29 +8,33 @@
|
||||
"test": {
|
||||
"dependsOn": [
|
||||
"@zitadel/node#build",
|
||||
"@zitadel/client2#build",
|
||||
"@zitadel/react#build"
|
||||
"@zitadel/client#build",
|
||||
"@zitadel/react#build",
|
||||
"@zitadel/next#build"
|
||||
]
|
||||
},
|
||||
"test:integration": {
|
||||
"dependsOn": [
|
||||
"@zitadel/node#build",
|
||||
"@zitadel/client2#build",
|
||||
"@zitadel/react#build"
|
||||
"@zitadel/client#build",
|
||||
"@zitadel/react#build",
|
||||
"@zitadel/next#build"
|
||||
]
|
||||
},
|
||||
"test:unit": {
|
||||
"dependsOn": [
|
||||
"@zitadel/node#build",
|
||||
"@zitadel/client2#build",
|
||||
"@zitadel/react#build"
|
||||
"@zitadel/client#build",
|
||||
"@zitadel/react#build",
|
||||
"@zitadel/next#build"
|
||||
]
|
||||
},
|
||||
"test:watch": {
|
||||
"dependsOn": [
|
||||
"@zitadel/node#build",
|
||||
"@zitadel/client2#build",
|
||||
"@zitadel/react#build"
|
||||
"@zitadel/client#build",
|
||||
"@zitadel/react#build",
|
||||
"@zitadel/next#build"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
12
package.json
Executable file → Normal file
12
package.json
Executable file → Normal file
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7",
|
||||
"private": true,
|
||||
"name": "typescript-monorepo",
|
||||
"scripts": {
|
||||
"generate": "turbo run generate",
|
||||
"build": "turbo run build",
|
||||
@@ -25,13 +26,14 @@
|
||||
"devDependencies": {
|
||||
"@changesets/cli": "^2.22.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"prettier": "^3.2.5",
|
||||
"tsup": "^8.0.2",
|
||||
"turbo": "^1.13.3",
|
||||
"prettier-plugin-organize-imports": "^4.0.0",
|
||||
"tsup": "^8.2.4",
|
||||
"turbo": "2.0.12",
|
||||
"typescript": "^5.4.5",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^1.6.0"
|
||||
"vite-tsconfig-paths": "^5.0.1",
|
||||
"vitest": "^2.0.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
"@typescript-eslint/parser": "^7.9.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-react": "^7.34.1",
|
||||
"eslint-config-turbo": "^1.13.3"
|
||||
"eslint-config-turbo": "^2.0.9"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# buf.gen.yaml
|
||||
version: v1
|
||||
managed:
|
||||
enabled: true
|
||||
plugins:
|
||||
# - plugin: buf.build/protocolbuffers/js
|
||||
# out: src/app/proto/generated
|
||||
# opt: import_style=commonjs,binary
|
||||
- plugin: buf.build/grpc/web
|
||||
out: src/proto/client
|
||||
opt: import_style=typescript,mode=grpcweb
|
||||
# - plugin: buf.build/grpc-ecosystem/openapiv2
|
||||
# out: src/app/proto/generated
|
||||
# opt: allow_delete_body
|
||||
@@ -1,37 +1,55 @@
|
||||
{
|
||||
"name": "@zitadel/client",
|
||||
"version": "0.0.0",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"./v1": {
|
||||
"import": "./dist/v1.js",
|
||||
"require": "./dist/v1.cjs",
|
||||
"types": "./dist/v1.d.ts"
|
||||
},
|
||||
"./v2": {
|
||||
"import": "./dist/v2.js",
|
||||
"require": "./dist/v2.cjs",
|
||||
"types": "./dist/v2.d.ts"
|
||||
},
|
||||
"./v3alpha": {
|
||||
"import": "./dist/v3alpha.js",
|
||||
"require": "./dist/v3alpha.cjs",
|
||||
"types": "./dist/v3alpha.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist/**"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"generate": "buf generate https://github.com/zitadel/zitadel.git --path ./proto/zitadel",
|
||||
"build": "tsup --dts",
|
||||
"build": "tsup",
|
||||
"test": "pnpm test:unit",
|
||||
"test:watch": "pnpm test:unit:watch",
|
||||
"test:unit": "vitest",
|
||||
"test:unit:watch": "vitest --watch",
|
||||
"dev": "tsup --watch --dts",
|
||||
"lint": "eslint \"src/**/*.ts*\"",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist && rm -rf src/proto"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bufbuild/buf": "^1.14.0",
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"ts-proto": "^1.139.0"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"jose": "^4.13.1",
|
||||
"nice-grpc-web": "^3.2.3",
|
||||
"protobufjs": "^7.2.3"
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"@bufbuild/protobuf": "^1.10.0",
|
||||
"@connectrpc/connect": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint-config-zitadel": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Return a slugified copy of a string.
|
||||
*
|
||||
* @param {CoreProps} str The ZITADEL client configuration
|
||||
* @return {Core} The client implementation.
|
||||
*/
|
||||
|
||||
let apps: ZitadelApp[] = [];
|
||||
|
||||
export interface ZitadelCoreProps {
|
||||
clientId: string;
|
||||
apiUrl: string; // process.env.ZITADEL_API_URL
|
||||
token: string;
|
||||
adminToken?: string;
|
||||
managementToken?: string;
|
||||
}
|
||||
|
||||
export interface ZitadelOptions extends ZitadelCoreProps {
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface ZitadelApp {
|
||||
name: string | undefined;
|
||||
config: ZitadelCoreProps;
|
||||
}
|
||||
|
||||
export async function initializeApp(
|
||||
config: ZitadelCoreProps,
|
||||
name?: string,
|
||||
): Promise<ZitadelApp> {
|
||||
const app = { config, name };
|
||||
return app;
|
||||
}
|
||||
|
||||
export function getApps(): ZitadelApp[] {
|
||||
return apps;
|
||||
}
|
||||
|
||||
export function getApp(name?: string): ZitadelApp | undefined {
|
||||
return name
|
||||
? apps.find((a) => a.name === name)
|
||||
: apps.length === 1
|
||||
? apps[0]
|
||||
: undefined;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { ZitadelApp } from "./app";
|
||||
import { authMiddleware } from "./middleware";
|
||||
|
||||
// const createClient = <Client>(
|
||||
// definition: CompatServiceDefinition,
|
||||
// accessToken: string
|
||||
// ) => {
|
||||
// const channel = createChannel(process.env.ZITADEL_API_URL ?? "");
|
||||
// return createClientFactory()
|
||||
// .use(authMiddleware(accessToken))
|
||||
// .create(definition, channel) as Client;
|
||||
// };
|
||||
|
||||
export async function getAuth(app?: ZitadelApp) {
|
||||
// return createClient<AuthServiceClient>(
|
||||
// AuthServiceDefinition as CompatServiceDefinition,
|
||||
// ""
|
||||
// );
|
||||
}
|
||||
@@ -1,5 +1,2 @@
|
||||
export { initializeApp, getApps } from "./app";
|
||||
|
||||
export { getAuth } from "./auth";
|
||||
|
||||
export type { ZitadelOptions } from "./app";
|
||||
export { NewAuthorizationBearerInterceptor } from "./interceptors";
|
||||
export type { PartialMessage, PlainMessage } from "@bufbuild/protobuf";
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
import { describe, expect, test, vitest } from "vitest";
|
||||
|
||||
import {
|
||||
CallOptions,
|
||||
ClientMiddlewareCall,
|
||||
Metadata,
|
||||
MethodDescriptor,
|
||||
} from "nice-grpc-web";
|
||||
import { authMiddleware } from "./middleware";
|
||||
|
||||
describe("authMiddleware", () => {
|
||||
const scenarios = [
|
||||
{
|
||||
name: "should add authorization if metadata is undefined",
|
||||
initialMetadata: undefined,
|
||||
expectedMetadata: new Metadata().set(
|
||||
"authorization",
|
||||
"Bearer mock-token",
|
||||
),
|
||||
token: "mock-token",
|
||||
},
|
||||
{
|
||||
name: "should add authorization if metadata exists but no authorization",
|
||||
initialMetadata: new Metadata().set("other-key", "other-value"),
|
||||
expectedMetadata: new Metadata()
|
||||
.set("other-key", "other-value")
|
||||
.set("authorization", "Bearer mock-token"),
|
||||
token: "mock-token",
|
||||
},
|
||||
{
|
||||
name: "should not modify authorization if it already exists",
|
||||
initialMetadata: new Metadata().set(
|
||||
"authorization",
|
||||
"Bearer initial-token",
|
||||
),
|
||||
expectedMetadata: new Metadata().set(
|
||||
"authorization",
|
||||
"Bearer initial-token",
|
||||
),
|
||||
token: "mock-token",
|
||||
},
|
||||
];
|
||||
|
||||
scenarios.forEach(({ name, initialMetadata, expectedMetadata, token }) => {
|
||||
test(name, async () => {
|
||||
const mockNext = vitest.fn().mockImplementation(async function* () {});
|
||||
const mockRequest = {};
|
||||
|
||||
const mockMethodDescriptor: MethodDescriptor = {
|
||||
options: { idempotencyLevel: undefined },
|
||||
path: "",
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
};
|
||||
|
||||
const mockCall: ClientMiddlewareCall<unknown, unknown> = {
|
||||
method: mockMethodDescriptor,
|
||||
requestStream: false,
|
||||
responseStream: false,
|
||||
request: mockRequest,
|
||||
next: mockNext,
|
||||
};
|
||||
const options: CallOptions = {
|
||||
metadata: initialMetadata,
|
||||
};
|
||||
|
||||
await authMiddleware(token)(mockCall, options).next();
|
||||
|
||||
expect(mockNext).toHaveBeenCalledTimes(1);
|
||||
const actualMetadata = mockNext.mock.calls[0][1].metadata;
|
||||
expect(actualMetadata?.get("authorization")).toEqual(
|
||||
expectedMetadata.get("authorization"),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
import { CallOptions, ClientMiddlewareCall, Metadata } from "nice-grpc-web";
|
||||
|
||||
export const authMiddleware = (token: string) =>
|
||||
async function* <Request, Response>(
|
||||
call: ClientMiddlewareCall<Request, Response>,
|
||||
options: CallOptions,
|
||||
) {
|
||||
if (!options.metadata?.has("authorization")) {
|
||||
options.metadata ??= new Metadata();
|
||||
options.metadata?.set("authorization", `Bearer ${token}`);
|
||||
}
|
||||
|
||||
return yield* call.next(call.request, options);
|
||||
};
|
||||
21
packages/zitadel-client/src/v2.ts
Normal file
21
packages/zitadel-client/src/v2.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { FeatureService } from "@zitadel/proto/zitadel/feature/v2/feature_service_connect";
|
||||
import { RequestContext } from "@zitadel/proto/zitadel/object/v2/object_pb";
|
||||
import { OIDCService } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_connect";
|
||||
import { OrganizationService } from "@zitadel/proto/zitadel/org/v2/org_service_connect";
|
||||
import { SessionService } from "@zitadel/proto/zitadel/session/v2/session_service_connect";
|
||||
import { SettingsService } from "@zitadel/proto/zitadel/settings/v2/settings_service_connect";
|
||||
import { UserService } from "@zitadel/proto/zitadel/user/v2/user_service_connect";
|
||||
import { createClientFor } from "./helpers";
|
||||
|
||||
export const createUserServiceClient = createClientFor(UserService);
|
||||
export const createSettingsServiceClient = createClientFor(SettingsService);
|
||||
export const createSessionServiceClient = createClientFor(SessionService);
|
||||
export const createOIDCServiceClient = createClientFor(OIDCService);
|
||||
export const createOrganizationServiceClient = createClientFor(OrganizationService);
|
||||
export const createFeatureServiceClient = createClientFor(FeatureService);
|
||||
|
||||
export function makeReqCtx(orgId: string | undefined): Partial<RequestContext> {
|
||||
return {
|
||||
resourceOwner: orgId ? { case: "orgId", value: orgId } : { case: "instance", value: true },
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
import { createClientFor } from "./helpers";
|
||||
import { UserSchemaService } from "@zitadel/proto/zitadel/user/schema/v3alpha/user_schema_service_connect";
|
||||
import { UserService } from "@zitadel/proto/zitadel/user/v3alpha/user_service_connect";
|
||||
import { ActionService } from "@zitadel/proto/zitadel/action/v3alpha/action_service_connect";
|
||||
import { createClientFor } from "./helpers";
|
||||
|
||||
export const createUserSchemaServiceClient = createClientFor(UserSchemaService);
|
||||
export const createUserServiceClient = createClientFor(UserService);
|
||||
export const createActionServiceClient = createClientFor(ActionService);
|
||||
@@ -1,13 +1,13 @@
|
||||
import { defineConfig, Options } from "tsup";
|
||||
|
||||
export default defineConfig((options: Options) => ({
|
||||
treeshake: true,
|
||||
splitting: true,
|
||||
publicDir: true,
|
||||
entry: ["src/index.ts", "src/**/index.ts"],
|
||||
entry: ["src/index.ts", "src/v1.ts", "src/v2.ts", "src/v3alpha.ts"],
|
||||
format: ["esm", "cjs"],
|
||||
treeshake: false,
|
||||
splitting: true,
|
||||
dts: true,
|
||||
minify: true,
|
||||
minify: false,
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
...options,
|
||||
}));
|
||||
|
||||
@@ -2,20 +2,14 @@
|
||||
"extends": [
|
||||
"//"
|
||||
],
|
||||
"pipeline": {
|
||||
"generate": {
|
||||
"outputs": [
|
||||
"src/proto/**"
|
||||
],
|
||||
"cache": true
|
||||
},
|
||||
"tasks": {
|
||||
"build": {
|
||||
"outputs": [
|
||||
"dist/**"
|
||||
],
|
||||
"dependsOn": [
|
||||
"generate"
|
||||
"@zitadel/proto#generate"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
{
|
||||
"name": "@zitadel/client2",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"./v1": {
|
||||
"import": "./dist/v1.js",
|
||||
"require": "./dist/v1.cjs",
|
||||
"types": "./dist/v1.d.ts"
|
||||
},
|
||||
"./v2beta": {
|
||||
"import": "./dist/v2beta.js",
|
||||
"require": "./dist/v2beta.cjs",
|
||||
"types": "./dist/v2beta.d.ts"
|
||||
},
|
||||
"./v3alpha": {
|
||||
"import": "./dist/v3alpha.js",
|
||||
"require": "./dist/v3alpha.cjs",
|
||||
"types": "./dist/v3alpha.d.ts"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"dist/**"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"test": "pnpm test:unit",
|
||||
"test:watch": "pnpm test:unit:watch",
|
||||
"test:unit": "vitest",
|
||||
"test:unit:watch": "vitest --watch",
|
||||
"dev": "tsup --watch --dts",
|
||||
"lint": "eslint \"src/**/*.ts*\"",
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"dependencies": {
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"@bufbuild/protobuf": "^1.9.0",
|
||||
"@connectrpc/connect": "^1.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint-config-zitadel": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export { NewAuthorizationBearerInterceptor } from "./interceptors";
|
||||
export type { PartialMessage, PlainMessage } from "@bufbuild/protobuf";
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { PartialMessage } from "@bufbuild/protobuf";
|
||||
|
||||
import { createClientFor } from "./helpers";
|
||||
import { UserService } from "@zitadel/proto/zitadel/user/v2beta/user_service_connect";
|
||||
import { SettingsService } from "@zitadel/proto/zitadel/settings/v2beta/settings_service_connect";
|
||||
import { SessionService } from "@zitadel/proto/zitadel/session/v2beta/session_service_connect";
|
||||
import { OIDCService } from "@zitadel/proto/zitadel/oidc/v2beta/oidc_service_connect";
|
||||
import { OrganizationService } from "@zitadel/proto/zitadel/org/v2beta/org_service_connect";
|
||||
import { FeatureService } from "@zitadel/proto/zitadel/feature/v2beta/feature_service_connect";
|
||||
import type { RequestContext } from "@zitadel/proto/zitadel/object/v2beta/object_pb";
|
||||
|
||||
export const createUserServiceClient = createClientFor(UserService);
|
||||
export const createSettingsServiceClient = createClientFor(SettingsService);
|
||||
export const createSessionServiceClient = createClientFor(SessionService);
|
||||
export const createOIDCServiceClient = createClientFor(OIDCService);
|
||||
export const createOrganizationServiceClient =
|
||||
createClientFor(OrganizationService);
|
||||
export const createFeatureServiceClient = createClientFor(FeatureService);
|
||||
|
||||
export function makeReqCtx(
|
||||
orgId: string | undefined,
|
||||
): PartialMessage<RequestContext> {
|
||||
return {
|
||||
resourceOwner: orgId
|
||||
? { case: "orgId", value: orgId }
|
||||
: { case: "instance", value: true },
|
||||
};
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": "@zitadel/tsconfig/tsup.json",
|
||||
"include": ["./src/**/*"],
|
||||
"exclude": ["dist", "build", "node_modules"]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { defineConfig, Options } from "tsup";
|
||||
|
||||
export default defineConfig((options: Options) => ({
|
||||
entry: ["src/index.ts", "src/v1.ts", "src/v2beta.ts", "src/v3alpha.ts"],
|
||||
format: ["esm", "cjs"],
|
||||
treeshake: false,
|
||||
splitting: true,
|
||||
dts: true,
|
||||
minify: false,
|
||||
clean: true,
|
||||
sourcemap: true,
|
||||
...options,
|
||||
}));
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"pipeline": {
|
||||
"build": {
|
||||
"outputs": ["dist/**"],
|
||||
"dependsOn": ["@zitadel/proto#generate"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"files": [
|
||||
"dist/**"
|
||||
],
|
||||
@@ -23,20 +24,22 @@
|
||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@zitadel/react": "workspace:*",
|
||||
"@zitadel/node": "workspace:*",
|
||||
"next": "^14.2.3",
|
||||
"react": "18.2.0"
|
||||
"@zitadel/react": "workspace:*",
|
||||
"@zitadel/client": "workspace:*",
|
||||
"@zitadel/proto": "workspace:*",
|
||||
"next": "^14.2.5",
|
||||
"react": "^18.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"next": "^14.2.3"
|
||||
"next": "^14.2.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^17.0.13",
|
||||
"@types/react": "^18.3.3",
|
||||
"@zitadel/tsconfig": "workspace:*",
|
||||
"eslint-config-zitadel": "workspace:*",
|
||||
"tailwindcss": "3.2.4",
|
||||
"postcss": "8.4.21",
|
||||
"postcss": "8.4.41",
|
||||
"tailwindcss": "3.4.9",
|
||||
"zitadel-tailwind-config": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import "./styles.css";
|
||||
// import "./styles.css";
|
||||
|
||||
export {
|
||||
ZitadelNextProvider,
|
||||
type ZitadelNextProps,
|
||||
} from "./components/ZitadelNextProvider";
|
||||
export { ZitadelNextProvider, type ZitadelNextProps } from "./components/ZitadelNextProvider";
|
||||
export * from "./utils/cookies";
|
||||
export { loadMostRecentSession } from "./utils/session";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user