Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 68 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# @zitadel/react Example
# @zitadel/react Quickstart SPA
<p align="center">
<img src="https://raw.githubusercontent.com/zitadel/zitadel/refs/heads/main/docs/static/logos/zitadel-logo-dark%402x.png" alt="Zitadel Logo" max-height="200px" width="auto" />
</p>

Authenticate your [ZITADEL](https://zitadel.com) users within your React applications.

Expand All @@ -19,33 +22,6 @@ The following pages are added to the scaffolded example application:
- _src/components/Login.tsx_: The login page shows a button if no user is authenticated and redirects the user to /callback if authenticated.
- _src/components/Callback.tsx_: This page completes the auth flow and renders the retrieved information from the user info endpoint.

## Run

To run the example, navigate to the `/lib` folder and run `yarn build`.

```bash
cd ./lib
yarn install
yarn build
```

then navigate back and install the dependencies of the example application

```bash
cd ..
yarn install
```

Next follow the guide for React applications in our [docs](https://zitadel.com/docs/examples/login/react)
and set `authority` as well as `client_id` in the `App.tsx` file.
Finally you can start the application with

```bash
yarn start
```

Your application will then run on `http://localhost:3000`.

## Available scripts

### `yarn start`
Expand All @@ -71,3 +47,67 @@ See the section about [deployment](https://facebook.github.io/create-react-app/d
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).

To learn React, check out the [React documentation](https://reactjs.org/).

## Setup Instructions
Comment thread
fcoppede marked this conversation as resolved.

1. **Log into the Zitadel Customer Portal**
Go to the [Zitadel Customer Portal](https://zitadel.com/admin/dashboard)

2. **Create an Instance**
- Choose a region and create your new instance.

3. **Create a Project**
- Inside your instance, go to Projects -> Create New Project

![App Screenshot](assets/new_project.png)

4. **Create an Application**
- New **"User Agent"**
- Select **"PKCE"**
- Enable **"Development Mode"**
- Configure your **Redirect URI** and **Post Logout URI** (`http://localhost:3000` for local testing)
- Click **"Continue"** and **"Create"**
- Copy the **"Client ID"**

![App Screenshot](assets/new_application.png)

5. **Change your token type to `JWT` in your application settings**
Comment thread
fcoppede marked this conversation as resolved.

![App Screenshot](assets/token_settings.png)

6. **Configure `ZitadelConfig`**
Open `src/App.tsx` and replace the placeholder for *authority* and *client_id* values with your application info:

```js
const config: ZitadelConfig = {
authority: "https://CUSTOM_DOMAIN",
client_id: "YOUR_CLIENT_ID",
redirect_uri: "http://localhost:3000/callback",
post_logout_redirect_uri: "http://localhost:3000",
response_type: 'code',
scope: 'openid profile email'
};
```

7. **Run the application**

To run the example, navigate to the `/lib` folder and run `yarn build`.

```bash
cd ./lib
yarn install
yarn build
```

Then, navigate back and install the dependencies

```bash
cd ..
yarn install
```

```bash
yarn start
```

Your application will then run on `http://localhost:3000`
Binary file added assets/new_application.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/new_project.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/token_settings.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 8 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ZITADEL React</title>
</head>
<head>
<meta charset="UTF-8">
<title>Zitadel React Quickstart SPA</title>
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap" rel="stylesheet">
<link rel="icon" type="image/x-icon" href="https://zitadel.com/docs/img/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css">
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/index.tsx"></script>
Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"author": "Max Peintner, <max@zitadel.com>",
"license": "MIT",
"dependencies": {
"oidc-client-ts": "^2.4.0"
"oidc-client-ts": "^3.3.0"
},
"devDependencies": {
"typescript": "^5.3.3"
Expand Down
30 changes: 12 additions & 18 deletions lib/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,19 @@
# yarn lockfile v1


crypto-js@^4.2.0:
version "4.2.0"
resolved "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz"
integrity sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==
jwt-decode@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b"
integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==

jwt-decode@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-3.1.2.tgz#3fb319f3675a2df0c2895c8f5e9fa4b67b04ed59"
integrity sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==

oidc-client-ts@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-2.4.0.tgz#764c8a33de542026e2798de9849ce8049047d7e5"
integrity sha512-WijhkTrlXK2VvgGoakWJiBdfIsVGz6CFzgjNNqZU1hPKV2kyeEaJgLs7RwuiSp2WhLfWBQuLvr2SxVlZnk3N1w==
oidc-client-ts@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/oidc-client-ts/-/oidc-client-ts-3.3.0.tgz#98a12e643b930825fb141634974e139d804ef972"
integrity sha512-t13S540ZwFOEZKLYHJwSfITugupW4uYLwuQSSXyKH/wHwZ+7FvgHE7gnNJh1YQIZ1Yd1hKSRjqeXGSUtS0r9JA==
dependencies:
crypto-js "^4.2.0"
jwt-decode "^3.1.2"
jwt-decode "^4.0.0"

typescript@^5.3.3:
version "5.3.3"
resolved "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz"
integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
version "5.9.2"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6"
integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"type": "module",
"dependencies": {
"@zitadel/react": "link:./lib",
"oidc-client-ts": "^2.4.0",
"bootstrap": "^5.3.8",
"oidc-client-ts": "^3.3.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.21.3"
Expand Down
79 changes: 33 additions & 46 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,56 +1,43 @@
.App {
text-align: center;
body {
font-family: 'Lato', sans-serif !important;
}

.App-logo {
height: 40vmin;
pointer-events: none;
.login-btn {
background-color: #5469D4 !important;
border-color: #5469D4 !important;
color: white !important;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
.logout-btn {
background-color:white !important;
border-color:#d4dae0 !important;
color: #CD3D56 !important;
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
.login-btn:hover,
.login-btn:focus,
.login-btn:active {
background-color: #5469D4 !important;
border-color: #5469D4 !important;
color: white !important;
}

.App-link {
color: #61dafb;
.logout-btn:hover,
.logout-btn:focus,
.logout-btn:active {
background-color: white !important;
border-color: #d4dae0 !important;
color: #CD3D56 !important;
}

button {
padding: 0.5rem 1rem;
background: white;
color: black;
border-radius: 0.5rem;
font-weight: 500;
border: 1px solid #333333;
}

.user {
font-size: 1rem;
}

.user .description {
font-size: 1rem;
margin-bottom: 1rem;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.jwt-box {
font-family: 'Courier New', Courier, monospace;
white-space: pre-wrap;
background-color: #f8f9fa;
/* Bootstrap light */
padding: 1rem;
border-radius: 0.5rem;
border: 1px solid #dee2e6;
max-width: 100%;
overflow-x: auto;
}
61 changes: 30 additions & 31 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { useEffect, useState } from 'react';
import logo from './logo.svg';
import './App.css';
import { createZitadelAuth, ZitadelConfig } from '@zitadel/react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { useEffect, useState } from "react";
import "./App.css";
import { createZitadelAuth, ZitadelConfig } from "@zitadel/react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import Navbar from "./components/Navbar"

import Login from './components/Login';
import Callback from './components/Callback';
import Login from "./components/Login";
import Callback from "./components/Callback";
import JWTContainer from "./components/JWTContainer";

function App() {

const config: ZitadelConfig = {
authority: "",
client_id: "",
authority: "https://CUSTOM_DOMAIN",
client_id: "YOUR_CLIENT_ID",
redirect_uri: "http://localhost:3000/callback",
post_logout_redirect_uri: "http://localhost:3000",
response_type: 'code',
scope: 'openid profile email'
};

const zitadel = createZitadelAuth(config);
Expand All @@ -19,46 +25,39 @@ function App() {
zitadel.authorize();
}

function signout() {
function logout() {
zitadel.signout();
}

const [authenticated, setAuthenticated] = useState<boolean | null>(null);
const [accessToken, setAccessToken] = useState<string | null>(null);
const [idToken, setIdToken] = useState<string | null>(null);

useEffect(() => {
zitadel.userManager.getUser().then(user => {
zitadel.userManager.getUser().then((user) => {
if (user) {
setAuthenticated(true);
setAccessToken(user.access_token ?? null);
setIdToken(user.id_token ?? null);
} else {
setAuthenticated(false);
setAccessToken(null);
setIdToken(null);
}
});
}, [zitadel]);

return (
<div className='App'>
<header className='App-header'>
<img src={logo} className='App-logo' alt='logo' />
<p>Welcome to ZITADEL React</p>

<div className="App">
<header className="App-header">
<BrowserRouter>
<Navbar />
<Login authenticated={authenticated} handleLogin={login} handleLogout={logout} />
<JWTContainer accessToken={accessToken} idToken={idToken} />
<Routes>
<Route
path='/'
element={
<Login authenticated={authenticated} handleLogin={login} />
}
/>
<Route
path='/callback'
element={
<Callback
authenticated={authenticated}
setAuth={setAuthenticated}
handleLogout={signout}
userManager={zitadel.userManager}
/>
}
path="/callback"
element={<Callback setAuth={setAuthenticated} userManager={zitadel.userManager} />}
/>
</Routes>
</BrowserRouter>
Expand Down
Loading