docs: Quickstart add frameworks (#11485)
# Which Problems Are Solved The quickstart only shows the steps to take to get a working zitadel login into your app with react. For users with another framework or languages we didn't show how to get to success fast. # How the Problems Are Solved - Adding different frameworks to the qucisktart example - Make sure the app configurations in the onboarding flow from the console match the configurations from the examples - Docs link in console onboarding flow point towards quickstart - Quickstart accepts framework selector, to pre select a framework from another page --------- Co-authored-by: Federico Coppede <[email protected]> Co-authored-by: Copilot <[email protected]>
@@ -0,0 +1,46 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useSearchParams } from 'next/navigation';
|
||||||
|
import { Tabs } from 'fumadocs-ui/components/tabs';
|
||||||
|
import { ReactNode, Suspense, useMemo } from 'react';
|
||||||
|
|
||||||
|
const FRAMEWORKS = ['angular', 'flutter', 'go', 'nextjs', 'react', 'symfony', 'vue'];
|
||||||
|
const DISPLAY_NAMES = ['Angular', 'Flutter', 'Go', 'Next.js', 'React', 'Symfony', 'Vue.js'];
|
||||||
|
|
||||||
|
function FrameworkSelectorInner({ children }: { children: ReactNode }) {
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
|
const activeIndex = useMemo(() => {
|
||||||
|
const query = searchParams.get('framework')?.toLowerCase();
|
||||||
|
if (!query) return 0;
|
||||||
|
|
||||||
|
// Strip dots/spaces to match 'nextjs' or 'vue' reliably
|
||||||
|
const sanitizedQuery = query.replace(/[\s.]/g, '');
|
||||||
|
const index = FRAMEWORKS.findIndex(f =>
|
||||||
|
f === sanitizedQuery || f.replace(/[\s.]/g, '') === sanitizedQuery
|
||||||
|
);
|
||||||
|
sessionStorage.setItem('framework-select', sanitizedQuery);
|
||||||
|
return index === -1 ? 0 : index;
|
||||||
|
}, [searchParams]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tabs
|
||||||
|
// Using a unique key based on the index forces the component
|
||||||
|
// to ignore any cached local storage state and use the new defaultIndex.
|
||||||
|
key={`framework-group-${activeIndex}`}
|
||||||
|
items={DISPLAY_NAMES}
|
||||||
|
defaultIndex={activeIndex}
|
||||||
|
groupId="framework-select"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Tabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FrameworkSelector(props: { children: ReactNode }) {
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<div className="h-40 w-full animate-pulse bg-fd-muted rounded-lg" />}>
|
||||||
|
<FrameworkSelectorInner {...props} />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -129,7 +129,7 @@ You will need to provide some values for the program to run:
|
|||||||
- `port`: The port on which the API will be accessible, default it 8089
|
- `port`: The port on which the API will be accessible, default it 8089
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
go run main.go --domain <custom domain> --key <key> -- clientID <clientID> --redirectURI <redirectURI>
|
go run main.go --domain <custom domain> --key <key> --clientID <clientID> --redirectURI <redirectURI>
|
||||||
```
|
```
|
||||||
|
|
||||||
This could look like:
|
This could look like:
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
export default function AppConfig({ redirectUrl, postLogoutRedirectUrl }) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<b>Auth Strategy</b>: <a href="/docs/apis/openidoauth/grant-types#authorization-code">Authorization Code Flow (PKCE)</a>. This modern standard ensures tokens are exchanged securely without needing a client secret in your frontend.
|
||||||
|
</li>
|
||||||
|
<li><b>Redirect URIs</b>: These define where users return after authentication:
|
||||||
|
<ul>
|
||||||
|
<li>Redirect URI: {redirectUrl} (Landing page after login)</li>
|
||||||
|
<li>Post Logout URI: {postLogoutRedirectUrl} (Landing page after logout)</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import ProjectClientIdImg from '@pub/img/guides/quickstart/project_client_id.png'
|
||||||
|
import ProjectClientIdSecretImg from '@pub/img/guides/quickstart/project_client_id_secret.png'
|
||||||
|
import ProjectUrlsImg from '@pub/img/guides/quickstart/project_urls.png'
|
||||||
|
import ProjectProjectIdImg from '@pub/img/guides/quickstart/project_project_id.png'
|
||||||
|
|
||||||
|
export default function AppValue({ valueCount, clientSecret, projectID }) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
To connect your application to ZITADEL, you need {valueCount} primary configuration values.
|
||||||
|
These are typically stored as environment variables in your project.
|
||||||
|
</p>
|
||||||
|
<ol>
|
||||||
|
{!!clientSecret == false && (<li>
|
||||||
|
<b>Client ID</b> Navigate to Configurations in the left sidebar. This is the unique public identifier for your React application.
|
||||||
|
<img
|
||||||
|
src={ProjectClientIdImg.src} alt="Get Client ID"/>
|
||||||
|
</li>)}
|
||||||
|
{!!clientSecret && (<li>
|
||||||
|
<b>Client ID & Client Secret</b> Copy the client id and secret from the modal. The client id is the unique public identifier for your application.
|
||||||
|
Note: If you missed copy the secret, you can generate a new one in the Actions dropdown.
|
||||||
|
<img
|
||||||
|
src={ProjectClientIdSecretImg.src} alt="Get Client ID and Secret"/>
|
||||||
|
</li>)}
|
||||||
|
<li>
|
||||||
|
<b>Issuer URL</b> Click on URLs in the left sidebar to find your <b>Discovery Endpoint</b>.
|
||||||
|
- The Value: Copy the issuer URL (e.g., https://your-instance.zitadel.cloud).
|
||||||
|
- Why it matters: ZITADEL supports OIDC Discovery. By providing just the Issuer URL to your SDK, the library automatically finds the login, logout, and token endpoints for you.
|
||||||
|
|
||||||
|
<img src={ProjectUrlsImg.src} alt="Get URLs"/>
|
||||||
|
</li>
|
||||||
|
{!!projectID && (<li >
|
||||||
|
<b>Project ID</b> Your currently in the application configuration which is a sub resource of the Project. Navigate to the Project with the back arrow and copy the Project ID.
|
||||||
|
|
||||||
|
<img src={ProjectProjectIdImg.src} alt="Get Project ID"/>
|
||||||
|
</li>)}
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,18 +1,16 @@
|
|||||||
---
|
---
|
||||||
title: The ZITADEL Quick Start Guide
|
title: The ZITADEL Quick Start Guide
|
||||||
description: Learn how to integrate OIDC PKCE authentication in React using ZITADEL in under 5 minutes.
|
description: Learn how to integrate OIDC PKCE authentication in your application using ZITADEL in under 5 minutes.
|
||||||
sidebar_label: Quick Start Guide
|
sidebar_label: Quick Start Guide
|
||||||
keywords: [ZITADEL, React, OIDC, PKCE, Authentication, Identity Management]
|
keywords: [ZITADEL, OIDC, PKCE, Authentication, Identity Management]
|
||||||
framework: React
|
|
||||||
stack: Node.js
|
|
||||||
---
|
---
|
||||||
|
|
||||||
import { ResponsivePlayer } from "@/components/player";
|
import { Tab } from 'fumadocs-ui/components/tabs';
|
||||||
|
import { FrameworkSelector } from '@/components/framework_selector';
|
||||||
|
import AppConfig from './_app_config.mdx';
|
||||||
|
import AppValues from './_app_values.mdx';
|
||||||
|
|
||||||
This sample app implements the [OIDC PKCE](/guides/integrate/login/oidc/login-users) flow for secure authentication.
|
In this guide, you’ll set up a Zitadel account and authenticate your first example application.
|
||||||
- Login: Exchanges a code challenge for an access token via ZITADEL.
|
|
||||||
- Authorize: Uses the token to retrieve profile data from the userinfo endpoint.
|
|
||||||
- Logout: Clears the local session and revokes the token.
|
|
||||||
|
|
||||||
## Get Started with ZITADEL Cloud
|
## Get Started with ZITADEL Cloud
|
||||||
|
|
||||||
@@ -34,8 +32,7 @@ This is the administrative hub for managing your billing, teams, and instances.
|
|||||||
|
|
||||||
Complete the brief onboarding questions.
|
Complete the brief onboarding questions.
|
||||||
This data helps us prioritize the development of new features, SDKs, and integrations that matter most to our community.
|
This data helps us prioritize the development of new features, SDKs, and integrations that matter most to our community.
|
||||||
|

|
||||||

|
|
||||||
|
|
||||||
### 3. Create your ZITADEL instance
|
### 3. Create your ZITADEL instance
|
||||||
|
|
||||||
@@ -65,33 +62,88 @@ Log in using the Admin credentials you just created.
|
|||||||
|
|
||||||
#### Step 1: Define your Project
|
#### Step 1: Define your Project
|
||||||
- **Name**: Enter a name (e.g., Project1).
|
- **Name**: Enter a name (e.g., Project1).
|
||||||
- **Framework**: Select React (or choose Other if your stack isn't listed).
|
- **Framework**: Select your preferred framework
|
||||||
- **Continue**: Click the Continue button.
|
- **Continue**: Click the Continue button.
|
||||||
|

|
||||||

|
|
||||||
|
|
||||||
#### Step 2: Review Default Configuration
|
#### Step 2: Review Default Configuration
|
||||||
ZITADEL automatically configures the best security settings for your selected framework.
|
ZITADEL automatically configures the best security settings for your selected framework.
|
||||||
- **Auth Strategy**: [Authorization Code Flow](/apis/openidoauth/grant-types#authorization-code) with [PKCE](/apis/openidoauth/grant-types#authorization-code). This modern standard ensures tokens are exchanged securely without needing a client secret in your frontend.
|
|
||||||
- **Redirect URIs**: These define where users return after authentication:
|
|
||||||
- Redirect URI: http://localhost:3000/callback (Landing page after login)
|
|
||||||
- Post Logout URI: http://localhost:3000/ (Landing page after logout)
|
|
||||||
|
|
||||||

|
<FrameworkSelector>
|
||||||
|
<Tab value="Angular">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:3000/auth/callback"
|
||||||
|
postLogoutRedirectUrl="http://localhost:3000/signedout">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:4444/auth.html, com.example.zitadelflutter"
|
||||||
|
postLogoutRedirectUrl="http://localhost:4444, com.example.zitadelflutter">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:8089/auth/callback"
|
||||||
|
postLogoutRedirectUrl="http://localhost:8089">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:3000/api/auth/callback/zitadel"
|
||||||
|
postLogoutRedirectUrl="http://localhost:3000/api/auth/logout/callback">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="React">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:3000/callback"
|
||||||
|
postLogoutRedirectUrl="http://localhost:3000/">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:8000/login_check"
|
||||||
|
postLogoutRedirectUrl="http://localhost:8000/logout">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
<AppConfig
|
||||||
|
redirectUrl="http://localhost:3000/auth/callback"
|
||||||
|
postLogoutRedirectUrl="http://localhost:3000/">
|
||||||
|
</AppConfig>
|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### 5. Collect your Integration Keys
|
### 5. Collect your Integration Keys
|
||||||
|
|
||||||
To connect your React application to ZITADEL, you need two primary configuration values.
|
<FrameworkSelector>
|
||||||
These are typically stored as environment variables in your project.
|
<Tab value="Angular">
|
||||||
|
<AppValues valueCount="two" clientSecret={false} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
<AppValues valueCount="two" clientSecret={false} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
<AppValues valueCount="two" clientSecret={false} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
<AppValues valueCount="three" clientSecret={true} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="React">
|
||||||
|
<AppValues valueCount="two" clientSecret={false} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
<AppValues valueCount="three" clientSecret={true} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
<AppValues valueCount="two" clientSecret={false} projectID={false}></AppValues>
|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
1. **Client ID** Navigate to Configurations in the left sidebar. This is the unique public identifier for your React application.
|
|
||||||

|
|
||||||
2. **Issuer URL** Click on URLs in the left sidebar to find your **Discovery Endpoint**.
|
|
||||||
- The Value: Copy the issuer URL (e.g., https://your-instance.zitadel.cloud).
|
|
||||||
- Why it matters: ZITADEL supports OIDC Discovery. By providing just the Issuer URL to your SDK, the library automatically finds the login, logout, and token endpoints for you.
|
|
||||||

|
|
||||||
|
|
||||||
## Integrate ZITADEL into your React App
|
## Integrate ZITADEL into your App
|
||||||
|
|
||||||
### How the Authentication Flow Works
|
### How the Authentication Flow Works
|
||||||
|
|
||||||
@@ -104,61 +156,266 @@ ZITADEL handles the complexity of the OIDC handshake so your app stays secure wi
|
|||||||
|
|
||||||
### 1. Prerequisites
|
### 1. Prerequisites
|
||||||
|
|
||||||
- [Node.js](https://nodejs.org/): v16 or later.
|
<FrameworkSelector>
|
||||||
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
<Tab value="Angular">
|
||||||
- [Yarn](https://yarnpkg.com/): This project uses Yarn for dependency management.
|
- [Node.js](https://nodejs.org/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
- [Flutter](https://docs.flutter.dev/install)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
- [Go](https://go.dev/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
- [Node.js](https://nodejs.org/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="React">
|
||||||
|
- [Node.js](https://nodejs.org/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
- [PHP](https://www.php.net/)
|
||||||
|
- [Composer](https://getcomposer.org/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
- [Node.js](https://nodejs.org/)
|
||||||
|
- Code Editor: [VS Code](https://code.visualstudio.com/) or similar
|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
### 2. Get the Example Project
|
### 2. Get the Example Project
|
||||||
|
|
||||||
Clone the repository and move into the project directory:
|
<FrameworkSelector>
|
||||||
```bash
|
<Tab value="Angular">
|
||||||
git clone https://github.com/zitadel/zitadel-react.git
|
```bash
|
||||||
cd zitadel-react
|
git clone https://github.com/zitadel/example-auth-angular.git
|
||||||
```
|
cd example-auth-angular
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/zitadel/zitadel_flutter.git
|
||||||
|
cd zitadel_flutter
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/zitadel/zitadel-go.git
|
||||||
|
cd zitadel_go
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
```bash
|
||||||
|
git clone [email protected]:zitadel/example-auth-nextjs.git
|
||||||
|
cd example-auth-nextjs
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="React">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/zitadel/example-auth-react.git
|
||||||
|
cd example-auth-react
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/zitadel/example-auth-symfony.git
|
||||||
|
cd example-auth-symfony
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
```bash
|
||||||
|
git clone [email protected]:zitadel/example-auth-vuejs.git
|
||||||
|
cd example-auth-vuejs
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
### 3. Build and Install
|
### 3. Configure your Credentials
|
||||||
|
|
||||||
Since this repo contains the SDK source, you need to build the library before running the example:
|
<FrameworkSelector>
|
||||||
```bash
|
<Tab value="Angular">
|
||||||
# Build the SDK library
|
|
||||||
cd lib && yarn install && yarn build
|
|
||||||
|
|
||||||
# Install example app dependencies
|
1. Copy+paste the .env.example to .env.local
|
||||||
cd .. && yarn install
|
2. Update the ZITADEL_CLIENT_ID and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Configure your Credentials
|
```bash
|
||||||
|
PORT=3000
|
||||||
|
NG_APP_ZITADEL_DOMAIN="https://your-zitadel-domain"
|
||||||
|
NG_APP_ZITADEL_CLIENT_ID="your-client-id"
|
||||||
|
NG_APP_ZITADEL_CALLBACK_URL="http://localhost:3000/auth/callback"
|
||||||
|
NG_APP_ZITADEL_POST_LOGOUT_URL="http://localhost:3000/auth/logout/callback"
|
||||||
|
NG_APP_ZITADEL_POST_LOGIN_URL="/profile"
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
No action required for this step.
|
||||||
|
The issuer and client Id will be passed directly when running the app (next step)
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
No action required for this step.
|
||||||
|
The issuer and client Id will be passed directly when running the app (next step)
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
1. Copy+past the .env.example to .env.local
|
||||||
|
2. Update the ZITADEL_CLIENT_ID, ZITADEL_CLIENT_SECRET and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
|
||||||
|
|
||||||
Open src/App.tsx and update the config object with the **Issuer** and **Client ID** you collected in Step 5.
|
```bash
|
||||||
|
NODE_ENV=development
|
||||||
|
PORT=3000
|
||||||
|
SESSION_SECRET="your-very-secret-and-strong-session-key"
|
||||||
|
SESSION_DURATION=3600
|
||||||
|
ZITADEL_DOMAIN="[https://your-instance.zitadel.cloud/](https://your-instance.zitadel.cloud/)"
|
||||||
|
ZITADEL_CLIENT_ID="zitadel-client-id"
|
||||||
|
ZITADEL_CLIENT_SECRET="zitadel-client-secret"
|
||||||
|
ZITADEL_CALLBACK_URL="http://localhost:3000/api/auth/callback/zitadel"
|
||||||
|
ZITADEL_POST_LOGIN_URL="/profile"
|
||||||
|
ZITADEL_POST_LOGOUT_URL="http://localhost:3000/api/auth/logout/callback"
|
||||||
|
NEXTAUTH_URL="http://localhost:3000"
|
||||||
|
|
||||||
```typescript
|
```
|
||||||
const config: ZitadelConfig = {
|
</Tab>
|
||||||
authority: "https://your-instance.zitadel.cloud", // Your Issuer URL
|
<Tab value="React">
|
||||||
client_id: "YOUR_CLIENT_ID", // Your Client ID
|
1. Copy+paste the .env.example to .env
|
||||||
redirect_uri: "http://localhost:3000/callback",
|
2. Update the ZITADEL_CLIENT_ID and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
|
||||||
post_logout_redirect_uri: "http://localhost:3000",
|
|
||||||
response_type: 'code',
|
|
||||||
scope: 'openid profile email'
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Run the Application
|
```bash
|
||||||
|
NODE_ENV=development
|
||||||
|
PORT=3000
|
||||||
|
VITE_ZITADEL_DOMAIN="https://your-zitadel-domain"
|
||||||
|
VITE_ZITADEL_CLIENT_ID="your-client-id"
|
||||||
|
VITE_ZITADEL_CALLBACK_URL="http://localhost:3000/auth/callback"
|
||||||
|
VITE_ZITADEL_POST_LOGIN_URL="/profile"
|
||||||
|
VITE_ZITADEL_POST_LOGOUT_URL="http://localhost:3000"
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
|
||||||
Start your development server:
|
1. Copy+paste the .env.example to .env
|
||||||
```bash
|
2. Update the ZITADEL_CLIENT_ID and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
|
||||||
yarn start
|
|
||||||
```
|
|
||||||
|
|
||||||
Your app will be live at `http://localhost:3000`. Click Login to test the full PKCE flow!
|
```bash
|
||||||
|
PORT=3000
|
||||||
|
NG_APP_ZITADEL_DOMAIN="https://your-zitadel-domain"
|
||||||
|
NG_APP_ZITADEL_CLIENT_ID="your-client-id"
|
||||||
|
NG_APP_ZITADEL_CALLBACK_URL="http://localhost:3000/auth/callback"
|
||||||
|
NG_APP_ZITADEL_POST_LOGOUT_URL="http://localhost:3000/auth/logout/callback"
|
||||||
|
NG_APP_ZITADEL_POST_LOGIN_URL="/profile"
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
1. Copy+paste the .env.example to .env
|
||||||
|
2. Update the ZITADEL_CLIENT_ID and ZITADEL_DOMAIN with the client id and issuer you collected in Step 5.
|
||||||
|
|
||||||

|
```bash
|
||||||
|
NODE_ENV=development
|
||||||
|
PORT=3000
|
||||||
|
VITE_ZITADEL_DOMAIN="https://your-zitadel-domain"
|
||||||
|
VITE_ZITADEL_CLIENT_ID="your-client-id"
|
||||||
|
VITE_ZITADEL_CALLBACK_URL="http://localhost:3000/auth/callback"
|
||||||
|
VITE_ZITADEL_POST_LOGIN_URL="/profile"
|
||||||
|
VITE_ZITADEL_POST_LOGOUT_URL="http://localhost:3000"
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
|
|
||||||
|
### 4. Build and Run
|
||||||
|
|
||||||
|
<FrameworkSelector>
|
||||||
|
<Tab value="Angular">
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:4200`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
<Tab value="Flutter">
|
||||||
|
Make sure to replace the [zitadel_issuer] and [zitadel_client_id] with your own value before running the command
|
||||||
|
```bash
|
||||||
|
flutter run -d chrome --web-port=4444 --dart-define zitadel_url=[zitadel_issuer] --dart-define zitadel_client_id=[zitadel_client_id]
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:4444`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
<Tab value="Go">
|
||||||
|
Make sure to replace the [zitadel_domain] (use the domain from the issuer without the https://) and [zitadel_client_id] with your own value before running the command
|
||||||
|
```bash
|
||||||
|
go run example/app/app.go --domain [zitadel_domain] --key XKv2Lqd7YAq13NUZVUWZEWZeruqyzViM --clientID [zitadel_client_id] --redirectURI http://localhost:8089/auth/callback
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:8089`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
<Tab value="Next.js">
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:3000`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</Tab>
|
||||||
|
<Tab value="React">
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:3000`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
<Tab value="Symfony">
|
||||||
|
```bash
|
||||||
|
composer install
|
||||||
|
composer run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:3000`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
<Tab value="Vue.js">
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Your app will be live at `http://localhost:3000`.
|
||||||
|
|
||||||
|

|
||||||
|
</Tab>
|
||||||
|
</FrameworkSelector>
|
||||||
|
|
||||||
## Success! 🚀
|
## Success! 🚀
|
||||||
You’ve successfully integrated ZITADEL into a React application.
|
You’ve successfully integrated ZITADEL into an application.
|
||||||
|
|
||||||
|
<Callout type="warn" title="Prevent Misconfiguration Lockouts">
|
||||||
|
Login policy misconfigurations that occur during the testing phase can easily lead to a [lockout](/legal/policies/account-lockout-policy). To ensure you don't lose access to your instance:
|
||||||
|
|
||||||
|
1. **Generate a backup PAT:** Create a [Service User Personal Access Token](/guides/integrate/service-users/personal-access-token) with the [`IAM_OWNER`](/guides/manage/console/managers) role to revert any login UI misconfigurations using the API.
|
||||||
|
2. **Add a second Instance Manager:** Always designate at least one [**second instance manager**](/guides/manage/console/managers).
|
||||||
|
|
||||||
|
</Callout>
|
||||||
|
|
||||||
### What’s next?
|
### What’s next?
|
||||||
|
- [**Example Applications**](/examples/introduction): Find more comprehensive guides and examples for the different frameworks
|
||||||
- [**SSO**](/guides/integrate/services): Learn how to add SSO to your services
|
- [**SSO**](/guides/integrate/services): Learn how to add SSO to your services
|
||||||
- [**Customize the UI**](/guides/manage/customize/branding): Make the login page your own with Branding.
|
- [**Customize the UI**](/guides/manage/customize/branding): Make the login page your own with Branding.
|
||||||
- [**Explore the API**](/apis/introduction): Check out the ZITADEL API Reference for advanced integrations.
|
- [**Explore the API**](/apis/introduction): Check out the ZITADEL API Reference for advanced integrations.
|
||||||
|
|
||||||
Need help? Join our [Discord community](https://zitadel.com/chat) or explore the full Documentation. Happy coding!
|
Need help? Join our [Discord community](https://zitadel.com/chat) or explore the full Documentation. Happy coding!
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"id": "client-go",
|
"id": "client-go",
|
||||||
"title": "Go",
|
"title": "Go",
|
||||||
"imgSrcDark": "/docs/img/tech/golang.svg",
|
"imgSrcDark": "/docs/img/tech/golang.svg",
|
||||||
"docsLink": "/docs/sdk-examples/go",
|
"docsLink": "/docs/guides/start/quickstart?framework=go",
|
||||||
"client": true,
|
"client": true,
|
||||||
"sdk": true
|
"sdk": true
|
||||||
},
|
},
|
||||||
@@ -48,18 +48,18 @@
|
|||||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||||
"imgSrcLight": "/docs/img/tech/angular.svg",
|
"imgSrcLight": "/docs/img/tech/angular.svg",
|
||||||
"imgSrcDark": "/docs/img/tech/angular.svg",
|
"imgSrcDark": "/docs/img/tech/angular.svg",
|
||||||
"docsLink": "/docs/sdk-examples/angular"
|
"docsLink": "/docs/guides/start/quickstart?framework=angular"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "flutter",
|
"id": "flutter",
|
||||||
"title": "Flutter",
|
"title": "Flutter",
|
||||||
"imgSrcDark": "/docs/img/tech/flutter.svg",
|
"imgSrcDark": "/docs/img/tech/flutter.svg",
|
||||||
"docsLink": "/docs/sdk-examples/flutter"
|
"docsLink": "/docs/guides/start/quickstart?framework=flutter"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Go",
|
"title": "Go",
|
||||||
"imgSrcDark": "/docs/img/tech/golang.svg",
|
"imgSrcDark": "/docs/img/tech/golang.svg",
|
||||||
"docsLink": "/docs/sdk-examples/go"
|
"docsLink": "/docs/guides/start/quickstart?framework=go"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "spring",
|
"id": "spring",
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
"title": "Next.js",
|
"title": "Next.js",
|
||||||
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
"imgSrcDark": "/docs/img/tech/nextjs.svg",
|
||||||
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
"imgSrcLight": "/docs/img/tech/nextjslight.svg",
|
||||||
"docsLink": "/docs/sdk-examples/nextjs"
|
"docsLink": "/docs/guides/start/quickstart?framework=nextjs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "django",
|
"id": "django",
|
||||||
@@ -103,20 +103,20 @@
|
|||||||
"title": "React",
|
"title": "React",
|
||||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||||
"imgSrcDark": "/docs/img/tech/react.svg",
|
"imgSrcDark": "/docs/img/tech/react.svg",
|
||||||
"docsLink": "/docs/sdk-examples/react"
|
"docsLink": "/docs/guides/start/quickstart?framework=react"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "symfony",
|
"id": "symfony",
|
||||||
"title": "Symfony",
|
"title": "Symfony",
|
||||||
"imgSrcDark": "/docs/img/tech/symfony.svg",
|
"imgSrcDark": "/docs/img/tech/symfony.svg",
|
||||||
"docsLink": "/docs/sdk-examples/symfony"
|
"docsLink": "/docs/guides/start/quickstart?framework=symfony"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "vue",
|
"id": "vue",
|
||||||
"title": "Vue.js",
|
"title": "Vue.js",
|
||||||
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
"description": "This preset sets up an OIDC configuration with Authentication Code Flow, secured by PKCE",
|
||||||
"imgSrcDark": "/docs/img/tech/vue.svg",
|
"imgSrcDark": "/docs/img/tech/vue.svg",
|
||||||
"docsLink": "/docs/sdk-examples/vue"
|
"docsLink": "/docs/guides/start/quickstart?framework=vue"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Dart",
|
"title": "Dart",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 350 KiB |
|
Before Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 264 KiB |
|
Before Width: | Height: | Size: 436 KiB |
|
Before Width: | Height: | Size: 277 KiB |
|
Before Width: | Height: | Size: 313 KiB |
|
Before Width: | Height: | Size: 935 KiB |
|
Before Width: | Height: | Size: 337 KiB |
|
Before Width: | Height: | Size: 265 KiB |
|
Before Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 314 KiB |
|
Before Width: | Height: | Size: 311 KiB |
|
Before Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 822 KiB |
|
Before Width: | Height: | Size: 350 KiB |
|
Before Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 449 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 607 KiB |
|
Before Width: | Height: | Size: 637 KiB |
|
Before Width: | Height: | Size: 636 KiB |
|
After Width: | Height: | Size: 98 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 291 KiB |
|
After Width: | Height: | Size: 362 KiB |
|
After Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 222 KiB After Width: | Height: | Size: 308 KiB |
|
After Width: | Height: | Size: 307 KiB |
|
Before Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 220 KiB |
|
Before Width: | Height: | Size: 312 KiB |
|
Before Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 480 KiB |
|
Before Width: | Height: | Size: 827 KiB |
|
Before Width: | Height: | Size: 439 KiB |
|
Before Width: | Height: | Size: 464 KiB |
|
Before Width: | Height: | Size: 575 KiB |
|
Before Width: | Height: | Size: 211 KiB |
|
After Width: | Height: | Size: 307 KiB |
@@ -17,6 +17,7 @@
|
|||||||
"incremental": true,
|
"incremental": true,
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./*"],
|
"@/*": ["./*"],
|
||||||
|
"@pub/*": ["./public/*"],
|
||||||
"fumadocs-mdx:collections/*": [".source/*"]
|
"fumadocs-mdx:collections/*": [".source/*"]
|
||||||
},
|
},
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
@@ -12,22 +12,22 @@ export const OIDC_CONFIGURATIONS: OidcAppConfigurations = {
|
|||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
||||||
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
||||||
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
||||||
.setRedirectUrisList(['http://localhost:4200/callback'])
|
.setRedirectUrisList(['http://localhost:3000/auth/callback'])
|
||||||
.setPostLogoutRedirectUrisList(['http://localhost:4200']),
|
.setPostLogoutRedirectUrisList(['http://localhost:3000/signedout']),
|
||||||
['react']: new AddOIDCAppRequest()
|
['react']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_USER_AGENT)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_USER_AGENT)
|
||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
||||||
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
||||||
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
||||||
.setRedirectUrisList(['http://localhost:3000/callback'])
|
.setRedirectUrisList(['http://localhost:3000/auth/callback'])
|
||||||
.setPostLogoutRedirectUrisList(['http://localhost:3000']),
|
.setPostLogoutRedirectUrisList(['http://localhost:3000']),
|
||||||
['vue']: new AddOIDCAppRequest()
|
['vue']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_USER_AGENT)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_USER_AGENT)
|
||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
||||||
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
||||||
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
||||||
.setRedirectUrisList(['http://localhost:5173/auth/signinwin/zitadel'])
|
.setRedirectUrisList(['http://localhost:3000/auth/callback'])
|
||||||
.setPostLogoutRedirectUrisList(['http://localhost:5173/']),
|
.setPostLogoutRedirectUrisList(['http://localhost:3000/']),
|
||||||
// web applications
|
// web applications
|
||||||
['next']: new AddOIDCAppRequest()
|
['next']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
||||||
@@ -80,11 +80,11 @@ export const OIDC_CONFIGURATIONS: OidcAppConfigurations = {
|
|||||||
.setPostLogoutRedirectUrisList(['http://localhost:3000']),
|
.setPostLogoutRedirectUrisList(['http://localhost:3000']),
|
||||||
['client-go']: new AddOIDCAppRequest()
|
['client-go']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
||||||
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
||||||
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
||||||
.setRedirectUrisList(['http://localhost:8080/auth/callback'])
|
.setRedirectUrisList(['http://localhost:8089/auth/callback'])
|
||||||
.setPostLogoutRedirectUrisList(['http://localhost:8080']),
|
.setPostLogoutRedirectUrisList(['http://localhost:8089']),
|
||||||
['client-ruby']: new AddOIDCAppRequest()
|
['client-ruby']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
|
||||||
@@ -97,8 +97,8 @@ export const OIDC_CONFIGURATIONS: OidcAppConfigurations = {
|
|||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_BASIC)
|
||||||
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
.setResponseTypesList([OIDCResponseType.OIDC_RESPONSE_TYPE_CODE])
|
||||||
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
.setGrantTypesList([OIDCGrantType.OIDC_GRANT_TYPE_AUTHORIZATION_CODE])
|
||||||
.setRedirectUrisList(['http://localhost:8000/login_check'])
|
.setRedirectUrisList(['http://localhost:3000/auth/callback'])
|
||||||
.setPostLogoutRedirectUrisList(['http://localhost:8000/logout']),
|
.setPostLogoutRedirectUrisList(['http://localhost:3000/auth/logout/callback']),
|
||||||
['django']: new AddOIDCAppRequest()
|
['django']: new AddOIDCAppRequest()
|
||||||
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
.setAppType(OIDCAppType.OIDC_APP_TYPE_WEB)
|
||||||
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
.setAuthMethodType(OIDCAuthMethodType.OIDC_AUTH_METHOD_TYPE_NONE)
|
||||||
|
|||||||