Skip to content

Commit bc33d36

Browse files
committed
added test for zitadel
1 parent b2d5c39 commit bc33d36

File tree

12 files changed

+294
-72
lines changed

12 files changed

+294
-72
lines changed

.github/workflows/test-google-oauth.yml

Lines changed: 0 additions & 54 deletions
This file was deleted.

.github/workflows/test-oauth.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Test OAuth
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
jobs:
11+
test-google-oauth:
12+
runs-on: ubuntu-latest
13+
env:
14+
##########################################################################
15+
# App Config
16+
##########################################################################
17+
NEXT_PUBLIC_URL: "http://localhost:3000"
18+
DATABASE_URI: "file:./payload-oauth2.db"
19+
PAYLOAD_SECRET: "hellohereisasecretforyou"
20+
21+
##########################################################################
22+
# Google OAuth Config
23+
##########################################################################
24+
GOOGLE_CLIENT_ID: ${{ secrets.GOOGLE_CLIENT_ID }}
25+
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
26+
27+
##########################################################################
28+
# Test Config
29+
##########################################################################
30+
# Optional: Set to "true" to run test browser in headless mode
31+
HEADLESS: true
32+
33+
##########################################################################
34+
# Google Test Account
35+
##########################################################################
36+
# Required: Google Test Account Email
37+
GOOGLE_TEST_EMAIL: ${{ secrets.GOOGLE_TEST_EMAIL }}
38+
39+
# Required: Google Test Account Password
40+
GOOGLE_TEST_PASSWORD: ${{ secrets.GOOGLE_TEST_PASSWORD }}
41+
42+
steps:
43+
- uses: actions/checkout@v4
44+
- uses: pnpm/action-setup@v2
45+
with:
46+
version: 9
47+
- uses: actions/setup-node@v4
48+
with:
49+
node-version: "20"
50+
cache: "pnpm"
51+
- run: |
52+
pnpx puppeteer browsers install chrome
53+
- run: pnpm install
54+
- run: pnpm test
55+
test-zitadel-oauth:
56+
runs-on: ubuntu-latest
57+
env:
58+
##########################################################################
59+
# App Config
60+
##########################################################################
61+
NEXT_PUBLIC_URL: "http://localhost:3000"
62+
DATABASE_URI: "file:./payload-oauth2.db"
63+
PAYLOAD_SECRET: "hellohereisasecretforyou"
64+
65+
##########################################################################
66+
# Zitadel OAuth Config
67+
##########################################################################
68+
ZITADEL_CLIENT_ID: ${{ secrets.ZITADEL_CLIENT_ID }}
69+
ZITADEL_CLIENT_SECRET: ${{ secrets.ZITADEL_CLIENT_SECRET }}
70+
ZITADEL_TOKEN_ENDPOINT: ${{ secrets.ZITADEL_TOKEN_ENDPOINT }}
71+
ZITADEL_AUTHORIZATION_URL: ${{ secrets.ZITADEL_AUTHORIZATION_URL }}
72+
ZITADEL_USERINFO_ENDPOINT: ${{ secrets.ZITADEL_USERINFO_ENDPOINT }}
73+
74+
##########################################################################
75+
# Test Config
76+
##########################################################################
77+
# Optional: Set to "true" to run test browser in headless mode
78+
HEADLESS: true
79+
80+
##########################################################################
81+
# Zitadel Test Account
82+
##########################################################################
83+
# Required: Zitadel Test Account Email
84+
ZITADEL_TEST_EMAIL: ${{ secrets.ZITADEL_TEST_EMAIL }}
85+
86+
# Required: Zitadel Test Account Password
87+
ZITADEL_TEST_PASSWORD: ${{ secrets.ZITADEL_TEST_PASSWORD }}
88+
89+
steps:
90+
- uses: actions/checkout@v4
91+
- uses: pnpm/action-setup@v2
92+
with:
93+
version: 9
94+
- uses: actions/setup-node@v4
95+
with:
96+
node-version: "20"
97+
cache: "pnpm"
98+
- run: |
99+
pnpx puppeteer browsers install chrome
100+
- run: pnpm install
101+
- run: pnpm test

dev/.env.example

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,14 @@ NEXT_PUBLIC_URL=http://localhost:3000
1616
# Optional: Google OAuth2 Client ID, not activated if not set
1717
# GOOGLE_CLIENT_ID=oauth2-client-id
1818

19-
# Required: Google OAuth2 Client Secret, not activated if not set
19+
# Optional: Google OAuth2 Client Secret, not activated if not set
2020
# GOOGLE_CLIENT_SECRET=oauth2-client-secret
21+
22+
################################################################################
23+
# zitadel oauth config
24+
################################################################################
25+
# optional: google oauth2 client id, not activated if not set
26+
ZITADEL_CLIENT_ID=298062958548846024
27+
28+
# optional: google oauth2 client secret, not activated if not set
29+
ZITADEL_CLIENT_SECRET=q2isqvfws3kg0af4ksiek3jigwre5utfoxgwkjj7mkbsmpgdyv1abyq6jcgpakch
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
import { OAuthLoginButton as OAuthLoginButton_cd47d145aed4cb23589a094917bd46e9 } from 'src/components/OAuthLoginButton'
1+
import { GoogleOAuthLoginButton as GoogleOAuthLoginButton_143f92647bcb7528bfe1082a22fc4d4e } from 'src/components/GoogleOAuthLoginButton'
2+
import { ZitadelOAuthLoginButton as ZitadelOAuthLoginButton_2b344d0256ae0172631ef421761722bb } from 'src/components/ZitadelOAuthLoginButton'
23

34
export const importMap = {
4-
"src/components/OAuthLoginButton#OAuthLoginButton": OAuthLoginButton_cd47d145aed4cb23589a094917bd46e9
5+
"src/components/GoogleOAuthLoginButton#GoogleOAuthLoginButton": GoogleOAuthLoginButton_143f92647bcb7528bfe1082a22fc4d4e,
6+
"src/components/ZitadelOAuthLoginButton#ZitadelOAuthLoginButton": ZitadelOAuthLoginButton_2b344d0256ae0172631ef421761722bb
57
}

dev/src/collections/Users.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ import { CollectionConfig } from "payload";
22

33
const Users: CollectionConfig = {
44
slug: "users",
5-
auth: {
6-
disableLocalStrategy: true,
7-
},
8-
admin: {
9-
useAsTitle: "email",
10-
},
5+
auth: { disableLocalStrategy: true },
6+
admin: { useAsTitle: "email" },
117
fields: [{ name: "email", type: "email", required: true }],
128
};
139

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"use client";
2+
export const GoogleOAuthLoginButton: React.FC = () => (
3+
<a href="/api/users/oauth/google">
4+
<button
5+
className="btn btn--icon-style-without-border btn--size-large btn--withoutPopup btn--style-primary btn--withoutPopup"
6+
style={{ width: "100%" }}
7+
>
8+
Continue With Google
9+
</button>
10+
</a>
11+
);

dev/src/components/OAuthLoginButton.tsx

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"use client";
2+
export const ZitadelOAuthLoginButton: React.FC = () => (
3+
<a href="/api/users/oauth/zitadel">
4+
<button
5+
className="btn btn--icon-style-without-border btn--size-large btn--withoutPopup btn--style-primary btn--withoutPopup"
6+
style={{ width: "100%" }}
7+
>
8+
Continue With Zitadel
9+
</button>
10+
</a>
11+
);

dev/src/payload.config.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ export default buildConfig({
1818
baseDir: path.resolve(dirname),
1919
},
2020
components: {
21-
afterLogin: ["src/components/OAuthLoginButton#OAuthLoginButton"],
21+
afterLogin: [
22+
"src/components/GoogleOAuthLoginButton#GoogleOAuthLoginButton",
23+
"src/components/ZitadelOAuthLoginButton#ZitadelOAuthLoginButton",
24+
],
2225
},
2326
user: Users.slug,
2427
},
@@ -44,6 +47,7 @@ export default buildConfig({
4447
clientId: process.env.GOOGLE_CLIENT_ID || "",
4548
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
4649
authorizePath: "/oauth/google",
50+
callbackPath: "/oauth/google/callback",
4751
authCollection: "users",
4852
tokenEndpoint: "https://oauth2.googleapis.com/token",
4953
scopes: [
@@ -68,6 +72,51 @@ export default buildConfig({
6872
return "/admin/login";
6973
},
7074
}),
75+
////////////////////////////////////////////////////////////////////////////
76+
// Zitadel OAuth
77+
////////////////////////////////////////////////////////////////////////////
78+
OAuth2Plugin({
79+
enabled:
80+
typeof process.env.ZITADEL_CLIENT_ID === "string" &&
81+
typeof process.env.ZITADEL_CLIENT_SECRET === "string" &&
82+
typeof process.env.ZITADEL_TOKEN_ENDPOINT === "string" &&
83+
typeof process.env.ZITADEL_AUTHORIZATION_URL === "string" &&
84+
typeof process.env.ZITADEL_USERINFO_ENDPOINT === "string",
85+
strategyName: "zitadel",
86+
useEmailAsIdentity: true,
87+
serverURL: process.env.NEXT_PUBLIC_URL || "http://localhost:3000",
88+
clientId: process.env.ZITADEL_CLIENT_ID || "",
89+
clientSecret: process.env.ZITADEL_CLIENT_SECRET || "",
90+
authorizePath: "/oauth/zitadel",
91+
callbackPath: "/oauth/zitadel/callback",
92+
authCollection: "users",
93+
tokenEndpoint: process.env.ZITADEL_TOKEN_ENDPOINT || "",
94+
scopes: [
95+
"openid",
96+
"profile",
97+
"email",
98+
"offline_access",
99+
"urn:zitadel:iam:user:metadata",
100+
],
101+
providerAuthorizationUrl: process.env.ZITADEL_AUTHORIZATION_URL || "",
102+
getUserInfo: async (accessToken: string) => {
103+
const response = await fetch(
104+
process.env.ZITADEL_USERINFO_ENDPOINT || "",
105+
{
106+
headers: { Authorization: `Bearer ${accessToken}` },
107+
},
108+
);
109+
const user = await response.json();
110+
return { email: user.email, sub: user.sub };
111+
},
112+
successRedirect: (req) => {
113+
return "/admin";
114+
},
115+
failureRedirect: (req, err) => {
116+
req.payload.logger.error(err);
117+
return "/admin/login";
118+
},
119+
}),
71120
],
72121
sharp,
73122
});

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"dev:build": "cross-env NODE_OPTIONS=--no-deprecation next build dev",
2525
"dev:start": "cross-env NODE_OPTIONS=--no-deprecation next start dev",
2626
"build": "tsc",
27-
"test": "cd test && jest --config=./jest.config.js",
27+
"test": "cd test && jest --config=./jest.config.js --runInBand",
2828
"format": "prettier --write src dev",
2929
"payload": "cd dev && cross-env NODE_OPTIONS=--no-deprecation payload",
3030
"dev:lint": "cd dev && cross-env NODE_OPTIONS=--no-deprecation next lint",

0 commit comments

Comments
 (0)