payload-zitadel-plugin 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ Thus the user collection in PayloadCMS becomes just a shadow of the information
12
12
  ## Install
13
13
 
14
14
  ```shell
15
- pnpm add payload-zitadel-plugin@0.2.6
15
+ pnpm add payload-zitadel-plugin@0.2.8
16
16
  ```
17
17
 
18
18
  ## Configuration
@@ -1,8 +1,8 @@
1
- export declare const ROUTES: {
2
- authorize: string;
3
- callback: string;
1
+ export declare const COOKIES: {
2
+ pkce: string;
3
+ idToken: string;
4
+ state: string;
4
5
  };
5
- export declare const COOKIE_ID_TOKEN = "id_token";
6
6
  export declare const DEFAULT_CONFIG: {
7
7
  associatedIdFieldName: string;
8
8
  strategyName: string;
@@ -20,4 +20,9 @@ export declare const ERROR_MESSAGES: {
20
20
  apiKeyId: string;
21
21
  apiKey: string;
22
22
  };
23
+ export declare const ROUTES: {
24
+ authorize: string;
25
+ callback: string;
26
+ redirect: string;
27
+ };
23
28
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM;;;CAGlB,CAAA;AAED,eAAO,MAAM,eAAe,aAAa,CAAA;AAEzC,eAAO,MAAM,cAAc;;;;CAI1B,CAAA;AAED,eAAO,MAAM,cAAc;;;;CAI1B,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;CAM1B,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO;;;;CAInB,CAAA;AAED,eAAO,MAAM,cAAc;;;;CAI1B,CAAA;AAED,eAAO,MAAM,cAAc;;;;CAI1B,CAAA;AAED,eAAO,MAAM,cAAc;;;;;;CAM1B,CAAA;AACD,eAAO,MAAM,MAAM;;;;CAIlB,CAAA"}
package/dist/constants.js CHANGED
@@ -1,8 +1,8 @@
1
- export const ROUTES = {
2
- authorize: '/authorize',
3
- callback: '/callback'
1
+ export const COOKIES = {
2
+ pkce: 'zitadel_pkce_code_verifier',
3
+ idToken: 'zitadel_id_token',
4
+ state: 'zitadel_state'
4
5
  };
5
- export const COOKIE_ID_TOKEN = 'id_token';
6
6
  export const DEFAULT_CONFIG = {
7
7
  associatedIdFieldName: 'idp_id',
8
8
  strategyName: 'zitadel',
@@ -20,5 +20,10 @@ export const ERROR_MESSAGES = {
20
20
  apiKeyId: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY-ID IS EMPTY',
21
21
  apiKey: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY IS EMPTY'
22
22
  };
23
+ export const ROUTES = {
24
+ authorize: '/authorize',
25
+ callback: '/callback',
26
+ redirect: '/redirect'
27
+ };
23
28
 
24
29
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["export const ROUTES = {\n authorize: '/authorize',\n callback: '/callback'\n}\n\nexport const COOKIE_ID_TOKEN = 'id_token'\n\nexport const DEFAULT_CONFIG = {\n associatedIdFieldName: 'idp_id',\n strategyName: 'zitadel',\n label: 'Zitadel'\n}\n\nexport const DELETE_ME_USER = {\n email: 'delete.me@now.not-tld',\n password: 'password',\n associatedId: 'DELETE_ME'\n}\n\nexport const ERROR_MESSAGES = {\n issuerURL: 'ZITADEL-PLUGIN: ISSUER-URL IS EMPTY',\n clientId: 'ZITADEL-PLUGIN: CLIENT-ID IS EMPTY',\n apiClientId: 'ZITADEL-PLUGIN: API ENABLED, BUT API-CLIENT-ID IS EMPTY',\n apiKeyId: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY-ID IS EMPTY',\n apiKey: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY IS EMPTY'\n}"],"names":["ROUTES","authorize","callback","COOKIE_ID_TOKEN","DEFAULT_CONFIG","associatedIdFieldName","strategyName","label","DELETE_ME_USER","email","password","associatedId","ERROR_MESSAGES","issuerURL","clientId","apiClientId","apiKeyId","apiKey"],"mappings":"AAAA,OAAO,MAAMA,SAAS;IAClBC,WAAW;IACXC,UAAU;AACd,EAAC;AAED,OAAO,MAAMC,kBAAkB,WAAU;AAEzC,OAAO,MAAMC,iBAAiB;IAC1BC,uBAAuB;IACvBC,cAAc;IACdC,OAAO;AACX,EAAC;AAED,OAAO,MAAMC,iBAAiB;IAC1BC,OAAO;IACPC,UAAU;IACVC,cAAc;AAClB,EAAC;AAED,OAAO,MAAMC,iBAAiB;IAC1BC,WAAW;IACXC,UAAU;IACVC,aAAa;IACbC,UAAU;IACVC,QAAQ;AACZ,EAAC"}
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["export const COOKIES = {\n pkce: 'zitadel_pkce_code_verifier',\n idToken: 'zitadel_id_token',\n state: 'zitadel_state'\n}\n\nexport const DEFAULT_CONFIG = {\n associatedIdFieldName: 'idp_id',\n strategyName: 'zitadel',\n label: 'Zitadel'\n}\n\nexport const DELETE_ME_USER = {\n email: 'delete.me@now.not-tld',\n password: 'password',\n associatedId: 'DELETE_ME'\n}\n\nexport const ERROR_MESSAGES = {\n issuerURL: 'ZITADEL-PLUGIN: ISSUER-URL IS EMPTY',\n clientId: 'ZITADEL-PLUGIN: CLIENT-ID IS EMPTY',\n apiClientId: 'ZITADEL-PLUGIN: API ENABLED, BUT API-CLIENT-ID IS EMPTY',\n apiKeyId: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY-ID IS EMPTY',\n apiKey: 'ZITADEL-PLUGIN: API ENABLED, BUT API-KEY IS EMPTY'\n}\nexport const ROUTES = {\n authorize: '/authorize',\n callback: '/callback',\n redirect: '/redirect'\n}\n\n"],"names":["COOKIES","pkce","idToken","state","DEFAULT_CONFIG","associatedIdFieldName","strategyName","label","DELETE_ME_USER","email","password","associatedId","ERROR_MESSAGES","issuerURL","clientId","apiClientId","apiKeyId","apiKey","ROUTES","authorize","callback","redirect"],"mappings":"AAAA,OAAO,MAAMA,UAAU;IACnBC,MAAM;IACNC,SAAS;IACTC,OAAO;AACX,EAAC;AAED,OAAO,MAAMC,iBAAiB;IAC1BC,uBAAuB;IACvBC,cAAc;IACdC,OAAO;AACX,EAAC;AAED,OAAO,MAAMC,iBAAiB;IAC1BC,OAAO;IACPC,UAAU;IACVC,cAAc;AAClB,EAAC;AAED,OAAO,MAAMC,iBAAiB;IAC1BC,WAAW;IACXC,UAAU;IACVC,aAAa;IACbC,UAAU;IACVC,QAAQ;AACZ,EAAC;AACD,OAAO,MAAMC,SAAS;IAClBC,WAAW;IACXC,UAAU;IACVC,UAAU;AACd,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/handlers/authorize.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAsBtC,eAAO,MAAM,SAAS,EAAE,cAcvB,CAAA"}
1
+ {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/handlers/authorize.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAuBtC,eAAO,MAAM,SAAS,EAAE,cAcvB,CAAA"}
@@ -2,10 +2,11 @@
2
2
  import { cookies } from 'next/headers.js';
3
3
  import process from 'node:process';
4
4
  import { NextResponse } from 'next/server.js';
5
+ import { COOKIES } from '../constants.js';
5
6
  const genCodeChallenge = async ()=>{
6
7
  const code_verifier = Buffer.from(crypto.getRandomValues(new Uint8Array(24))).toString('base64url');
7
8
  cookies().set({
8
- name: 'pkce_code_verifier',
9
+ name: COOKIES.pkce,
9
10
  value: code_verifier,
10
11
  httpOnly: true,
11
12
  sameSite: 'lax',
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/handlers/authorize.ts"],"sourcesContent":["'use server'\n\nimport {cookies} from 'next/headers.js'\nimport process from 'node:process'\nimport {PayloadHandler} from 'payload'\nimport {NextResponse} from 'next/server.js'\nimport {PayloadConfigWithZitadel} from '../types.js'\n\nconst genCodeChallenge = async () => {\n\n const code_verifier = Buffer.from(crypto.getRandomValues(new Uint8Array(24))).toString('base64url')\n\n cookies().set({\n name: 'pkce_code_verifier',\n value: code_verifier,\n httpOnly: true,\n sameSite: 'lax',\n path: '/',\n maxAge: 300,\n secure: process.env.NODE_ENV == 'production'\n })\n\n return Buffer.from(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(code_verifier))).toString('base64url')\n\n}\n\nexport const authorize: PayloadHandler = async ({searchParams, payload: {config}}) => {\n\n const {admin: {custom: {zitadel: {issuerURL, clientId, callbackURL}}}} = config as PayloadConfigWithZitadel\n\n return NextResponse.redirect(`${issuerURL}/oauth/v2/authorize?${new URLSearchParams({\n client_id: clientId,\n redirect_uri: callbackURL,\n response_type: 'code',\n scope: 'openid email profile',\n state: btoa(searchParams.toString()),\n code_challenge: await genCodeChallenge(),\n code_challenge_method: 'S256'\n })}`)\n\n}\n"],"names":["cookies","process","NextResponse","genCodeChallenge","code_verifier","Buffer","from","crypto","getRandomValues","Uint8Array","toString","set","name","value","httpOnly","sameSite","path","maxAge","secure","env","NODE_ENV","subtle","digest","TextEncoder","encode","authorize","searchParams","payload","config","admin","custom","zitadel","issuerURL","clientId","callbackURL","redirect","URLSearchParams","client_id","redirect_uri","response_type","scope","state","btoa","code_challenge","code_challenge_method"],"mappings":"AAAA;AAEA,SAAQA,OAAO,QAAO,kBAAiB;AACvC,OAAOC,aAAa,eAAc;AAElC,SAAQC,YAAY,QAAO,iBAAgB;AAG3C,MAAMC,mBAAmB;IAErB,MAAMC,gBAAgBC,OAAOC,IAAI,CAACC,OAAOC,eAAe,CAAC,IAAIC,WAAW,MAAMC,QAAQ,CAAC;IAEvFV,UAAUW,GAAG,CAAC;QACVC,MAAM;QACNC,OAAOT;QACPU,UAAU;QACVC,UAAU;QACVC,MAAM;QACNC,QAAQ;QACRC,QAAQjB,QAAQkB,GAAG,CAACC,QAAQ,IAAI;IACpC;IAEA,OAAOf,OAAOC,IAAI,CAAC,MAAMC,OAAOc,MAAM,CAACC,MAAM,CAAC,WAAW,IAAIC,cAAcC,MAAM,CAACpB,iBAAiBM,QAAQ,CAAC;AAEhH;AAEA,OAAO,MAAMe,YAA4B,OAAO,EAACC,YAAY,EAAEC,SAAS,EAACC,MAAM,EAAC,EAAC;IAE7E,MAAM,EAACC,OAAO,EAACC,QAAQ,EAACC,SAAS,EAACC,SAAS,EAAEC,QAAQ,EAAEC,WAAW,EAAC,EAAC,EAAC,EAAC,GAAGN;IAEzE,OAAO1B,aAAaiC,QAAQ,CAAC,CAAC,EAAEH,UAAU,oBAAoB,EAAE,IAAII,gBAAgB;QAChFC,WAAWJ;QACXK,cAAcJ;QACdK,eAAe;QACfC,OAAO;QACPC,OAAOC,KAAKhB,aAAahB,QAAQ;QACjCiC,gBAAgB,MAAMxC;QACtByC,uBAAuB;IAC3B,GAAG,CAAC;AAER,EAAC"}
1
+ {"version":3,"sources":["../../src/handlers/authorize.ts"],"sourcesContent":["'use server'\n\nimport {cookies} from 'next/headers.js'\nimport process from 'node:process'\nimport {PayloadHandler} from 'payload'\nimport {NextResponse} from 'next/server.js'\nimport {PayloadConfigWithZitadel} from '../types.js'\nimport {COOKIES} from '../constants.js'\n\nconst genCodeChallenge = async () => {\n\n const code_verifier = Buffer.from(crypto.getRandomValues(new Uint8Array(24))).toString('base64url')\n\n cookies().set({\n name: COOKIES.pkce,\n value: code_verifier,\n httpOnly: true,\n sameSite: 'lax',\n path: '/',\n maxAge: 300,\n secure: process.env.NODE_ENV == 'production'\n })\n\n return Buffer.from(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(code_verifier))).toString('base64url')\n\n}\n\nexport const authorize: PayloadHandler = async ({searchParams, payload: {config}}) => {\n\n const {admin: {custom: {zitadel: {issuerURL, clientId, callbackURL}}}} = config as PayloadConfigWithZitadel\n\n return NextResponse.redirect(`${issuerURL}/oauth/v2/authorize?${new URLSearchParams({\n client_id: clientId,\n redirect_uri: callbackURL,\n response_type: 'code',\n scope: 'openid email profile',\n state: btoa(searchParams.toString()),\n code_challenge: await genCodeChallenge(),\n code_challenge_method: 'S256'\n })}`)\n\n}\n"],"names":["cookies","process","NextResponse","COOKIES","genCodeChallenge","code_verifier","Buffer","from","crypto","getRandomValues","Uint8Array","toString","set","name","pkce","value","httpOnly","sameSite","path","maxAge","secure","env","NODE_ENV","subtle","digest","TextEncoder","encode","authorize","searchParams","payload","config","admin","custom","zitadel","issuerURL","clientId","callbackURL","redirect","URLSearchParams","client_id","redirect_uri","response_type","scope","state","btoa","code_challenge","code_challenge_method"],"mappings":"AAAA;AAEA,SAAQA,OAAO,QAAO,kBAAiB;AACvC,OAAOC,aAAa,eAAc;AAElC,SAAQC,YAAY,QAAO,iBAAgB;AAE3C,SAAQC,OAAO,QAAO,kBAAiB;AAEvC,MAAMC,mBAAmB;IAErB,MAAMC,gBAAgBC,OAAOC,IAAI,CAACC,OAAOC,eAAe,CAAC,IAAIC,WAAW,MAAMC,QAAQ,CAAC;IAEvFX,UAAUY,GAAG,CAAC;QACVC,MAAMV,QAAQW,IAAI;QAClBC,OAAOV;QACPW,UAAU;QACVC,UAAU;QACVC,MAAM;QACNC,QAAQ;QACRC,QAAQnB,QAAQoB,GAAG,CAACC,QAAQ,IAAI;IACpC;IAEA,OAAOhB,OAAOC,IAAI,CAAC,MAAMC,OAAOe,MAAM,CAACC,MAAM,CAAC,WAAW,IAAIC,cAAcC,MAAM,CAACrB,iBAAiBM,QAAQ,CAAC;AAEhH;AAEA,OAAO,MAAMgB,YAA4B,OAAO,EAACC,YAAY,EAAEC,SAAS,EAACC,MAAM,EAAC,EAAC;IAE7E,MAAM,EAACC,OAAO,EAACC,QAAQ,EAACC,SAAS,EAACC,SAAS,EAAEC,QAAQ,EAAEC,WAAW,EAAC,EAAC,EAAC,EAAC,GAAGN;IAEzE,OAAO5B,aAAamC,QAAQ,CAAC,CAAC,EAAEH,UAAU,oBAAoB,EAAE,IAAII,gBAAgB;QAChFC,WAAWJ;QACXK,cAAcJ;QACdK,eAAe;QACfC,OAAO;QACPC,OAAOC,KAAKhB,aAAajB,QAAQ;QACjCkC,gBAAgB,MAAMzC;QACtB0C,uBAAuB;IAC3B,GAAG,CAAC;AAER,EAAC"}
@@ -1,4 +1,3 @@
1
1
  import { PayloadHandler } from 'payload';
2
- import { ZitadelOnSuccess } from '../types.js';
3
- export declare const callback: (onSuccess: ZitadelOnSuccess) => PayloadHandler;
2
+ export declare const callback: PayloadHandler;
4
3
  //# sourceMappingURL=callback.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../src/handlers/callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAItC,OAAO,EAA2C,gBAAgB,EAAC,MAAM,aAAa,CAAA;AAEtF,eAAO,MAAM,QAAQ,cAAe,gBAAgB,KAAG,cA+DtD,CAAA"}
1
+ {"version":3,"file":"callback.d.ts","sourceRoot":"","sources":["../../src/handlers/callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAQtC,eAAO,MAAM,QAAQ,EAAE,cA4EtB,CAAA"}
@@ -1,50 +1,62 @@
1
1
  import { cookies } from 'next/headers.js';
2
2
  import process from 'node:process';
3
3
  import jwt from 'jsonwebtoken';
4
- export const callback = (onSuccess)=>async ({ payload, query: { code, state } })=>{
5
- const { secret, admin: { custom: { zitadel: { issuerURL, clientId, callbackURL } } } } = payload.config;
6
- const cookieStore = cookies();
7
- const code_verifier = cookieStore.get('pkce_code_verifier')?.value;
8
- if (code_verifier) {
9
- const response = await fetch(new URL(`${issuerURL}/oauth/v2/token`), {
10
- method: 'POST',
11
- body: new URLSearchParams({
12
- grant_type: 'authorization_code',
13
- code: code,
14
- redirect_uri: callbackURL,
15
- client_id: clientId,
16
- code_verifier
17
- })
18
- });
19
- if (response.ok) {
20
- const { id_token } = await response.json();
21
- if (id_token) {
22
- cookieStore.set({
23
- name: 'id_token',
24
- value: jwt.sign(jwt.decode(id_token), secret),
25
- httpOnly: true,
26
- path: '/',
27
- sameSite: 'strict',
28
- maxAge: 900,
29
- secure: process.env.NODE_ENV == 'production'
30
- });
31
- cookieStore.delete('pkce_code_verifier');
32
- return onSuccess(new URLSearchParams(atob(state ?? '')));
33
- }
34
- return Response.json({
35
- status: 'error',
36
- message: 'token could not be retrieved from the response'
4
+ import { NextResponse } from 'next/server.js';
5
+ import { COOKIES } from '../constants.js';
6
+ export const callback = async ({ payload: { config, secret }, responseHeaders, origin, query: { code, state } })=>{
7
+ const { admin: { custom: { zitadel: { issuerURL, clientId, callbackURL } } } } = config;
8
+ const cookieStore = cookies();
9
+ const code_verifier = cookieStore.get(COOKIES.pkce)?.value;
10
+ if (code_verifier) {
11
+ const response = await fetch(new URL(`${issuerURL}/oauth/v2/token`), {
12
+ method: 'POST',
13
+ body: new URLSearchParams({
14
+ grant_type: 'authorization_code',
15
+ code: code,
16
+ redirect_uri: callbackURL,
17
+ client_id: clientId,
18
+ code_verifier
19
+ })
20
+ });
21
+ if (response.ok) {
22
+ const { id_token } = await response.json();
23
+ if (id_token) {
24
+ cookieStore.set({
25
+ name: COOKIES.idToken,
26
+ value: jwt.sign(jwt.decode(id_token), secret),
27
+ httpOnly: true,
28
+ path: '/',
29
+ sameSite: 'strict',
30
+ maxAge: 900,
31
+ secure: process.env.NODE_ENV == 'production'
32
+ });
33
+ cookieStore.delete('pkce_code_verifier');
34
+ const response = NextResponse.redirect(`${new URL(callbackURL).origin}/admin/login`);
35
+ response.cookies.set({
36
+ name: COOKIES.state,
37
+ value: state ?? '',
38
+ httpOnly: true,
39
+ path: '/',
40
+ sameSite: 'lax',
41
+ maxAge: 300,
42
+ secure: process.env.NODE_ENV == 'production'
37
43
  });
44
+ return response;
38
45
  }
39
46
  return Response.json({
40
47
  status: 'error',
41
- message: 'error while communicating with token endpoint'
48
+ message: 'token could not be retrieved from the response'
42
49
  });
43
50
  }
44
51
  return Response.json({
45
52
  status: 'error',
46
- message: 'code verifier not found (associated http-only cookie is empty)'
53
+ message: 'error while communicating with token endpoint'
47
54
  });
48
- };
55
+ }
56
+ return Response.json({
57
+ status: 'error',
58
+ message: 'code verifier not found (associated http-only cookie is empty)'
59
+ });
60
+ };
49
61
 
50
62
  //# sourceMappingURL=callback.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/handlers/callback.ts"],"sourcesContent":["import {PayloadHandler} from 'payload'\nimport {cookies} from 'next/headers.js'\nimport process from 'node:process'\nimport jwt from 'jsonwebtoken'\nimport {PayloadConfigWithZitadel, ZitadelIdToken, ZitadelOnSuccess} from '../types.js'\n\nexport const callback = (onSuccess: ZitadelOnSuccess): PayloadHandler => async ({payload, query: {code, state}}) => {\n\n const {\n secret,\n admin: {custom: {zitadel: {issuerURL, clientId, callbackURL}}}\n } = payload.config as PayloadConfigWithZitadel\n\n const cookieStore = cookies()\n\n const code_verifier = cookieStore.get('pkce_code_verifier')?.value\n\n if (code_verifier) {\n\n const response = await fetch(new URL(`${issuerURL}/oauth/v2/token`), {\n method: 'POST',\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code: code as string,\n redirect_uri: callbackURL,\n client_id: clientId,\n code_verifier\n })\n })\n\n if (response.ok) {\n\n const {id_token} = await response.json()\n\n if (id_token) {\n cookieStore.set({\n name: 'id_token',\n value: jwt.sign(jwt.decode(id_token) as ZitadelIdToken, secret),\n httpOnly: true,\n path: '/',\n sameSite: 'strict',\n maxAge: 900,\n secure: process.env.NODE_ENV == 'production'\n })\n cookieStore.delete('pkce_code_verifier')\n\n return onSuccess(new URLSearchParams(atob(state as string ?? '')))\n\n }\n\n return Response.json({\n status: 'error',\n message: 'token could not be retrieved from the response'\n })\n\n }\n\n return Response.json({\n status: 'error',\n message: 'error while communicating with token endpoint'\n })\n\n }\n\n return Response.json({\n status: 'error',\n message: 'code verifier not found (associated http-only cookie is empty)'\n })\n\n}"],"names":["cookies","process","jwt","callback","onSuccess","payload","query","code","state","secret","admin","custom","zitadel","issuerURL","clientId","callbackURL","config","cookieStore","code_verifier","get","value","response","fetch","URL","method","body","URLSearchParams","grant_type","redirect_uri","client_id","ok","id_token","json","set","name","sign","decode","httpOnly","path","sameSite","maxAge","secure","env","NODE_ENV","delete","atob","Response","status","message"],"mappings":"AACA,SAAQA,OAAO,QAAO,kBAAiB;AACvC,OAAOC,aAAa,eAAc;AAClC,OAAOC,SAAS,eAAc;AAG9B,OAAO,MAAMC,WAAW,CAACC,YAAgD,OAAO,EAACC,OAAO,EAAEC,OAAO,EAACC,IAAI,EAAEC,KAAK,EAAC,EAAC;QAE3G,MAAM,EACFC,MAAM,EACNC,OAAO,EAACC,QAAQ,EAACC,SAAS,EAACC,SAAS,EAAEC,QAAQ,EAAEC,WAAW,EAAC,EAAC,EAAC,EACjE,GAAGV,QAAQW,MAAM;QAElB,MAAMC,cAAcjB;QAEpB,MAAMkB,gBAAgBD,YAAYE,GAAG,CAAC,uBAAuBC;QAE7D,IAAIF,eAAe;YAEf,MAAMG,WAAW,MAAMC,MAAM,IAAIC,IAAI,CAAC,EAAEV,UAAU,eAAe,CAAC,GAAG;gBACjEW,QAAQ;gBACRC,MAAM,IAAIC,gBAAgB;oBACtBC,YAAY;oBACZpB,MAAMA;oBACNqB,cAAcb;oBACdc,WAAWf;oBACXI;gBACJ;YACJ;YAEA,IAAIG,SAASS,EAAE,EAAE;gBAEb,MAAM,EAACC,QAAQ,EAAC,GAAG,MAAMV,SAASW,IAAI;gBAEtC,IAAID,UAAU;oBACVd,YAAYgB,GAAG,CAAC;wBACZC,MAAM;wBACNd,OAAOlB,IAAIiC,IAAI,CAACjC,IAAIkC,MAAM,CAACL,WAA6BtB;wBACxD4B,UAAU;wBACVC,MAAM;wBACNC,UAAU;wBACVC,QAAQ;wBACRC,QAAQxC,QAAQyC,GAAG,CAACC,QAAQ,IAAI;oBACpC;oBACA1B,YAAY2B,MAAM,CAAC;oBAEnB,OAAOxC,UAAU,IAAIsB,gBAAgBmB,KAAKrC,SAAmB;gBAEjE;gBAEA,OAAOsC,SAASd,IAAI,CAAC;oBACjBe,QAAQ;oBACRC,SAAS;gBACb;YAEJ;YAEA,OAAOF,SAASd,IAAI,CAAC;gBACjBe,QAAQ;gBACRC,SAAS;YACb;QAEJ;QAEA,OAAOF,SAASd,IAAI,CAAC;YACjBe,QAAQ;YACRC,SAAS;QACb;IAEJ,EAAC"}
1
+ {"version":3,"sources":["../../src/handlers/callback.ts"],"sourcesContent":["import {PayloadHandler} from 'payload'\nimport {cookies} from 'next/headers.js'\nimport process from 'node:process'\nimport jwt from 'jsonwebtoken'\nimport {PayloadConfigWithZitadel, ZitadelIdToken} from '../types.js'\nimport {NextResponse} from 'next/server.js'\nimport {COOKIES} from '../constants.js'\n\nexport const callback: PayloadHandler = async ({\n payload: {config, secret},\n responseHeaders,\n origin,\n query: {code, state}\n }) => {\n\n const {admin: {custom: {zitadel: {issuerURL, clientId, callbackURL}}}} = config as PayloadConfigWithZitadel\n\n const cookieStore = cookies()\n\n const code_verifier = cookieStore.get(COOKIES.pkce)?.value\n\n if (code_verifier) {\n\n const response = await fetch(new URL(`${issuerURL}/oauth/v2/token`), {\n method: 'POST',\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n code: code as string,\n redirect_uri: callbackURL,\n client_id: clientId,\n code_verifier\n })\n })\n\n if (response.ok) {\n\n const {id_token} = await response.json()\n\n if (id_token) {\n\n cookieStore.set({\n name: COOKIES.idToken,\n value: jwt.sign(jwt.decode(id_token) as ZitadelIdToken, secret),\n httpOnly: true,\n path: '/',\n sameSite: 'strict',\n maxAge: 900,\n secure: process.env.NODE_ENV == 'production'\n })\n cookieStore.delete('pkce_code_verifier')\n\n const response = NextResponse.redirect(`${new URL(callbackURL).origin}/admin/login`)\n response.cookies.set({\n name: COOKIES.state,\n value: state as string ?? '',\n httpOnly: true,\n path: '/',\n sameSite: 'lax',\n maxAge: 300,\n secure: process.env.NODE_ENV == 'production'\n })\n return response\n\n }\n\n return Response.json({\n status: 'error',\n message: 'token could not be retrieved from the response'\n })\n\n }\n\n return Response.json({\n status: 'error',\n message: 'error while communicating with token endpoint'\n })\n\n }\n\n return Response.json({\n status: 'error',\n message: 'code verifier not found (associated http-only cookie is empty)'\n })\n\n}"],"names":["cookies","process","jwt","NextResponse","COOKIES","callback","payload","config","secret","responseHeaders","origin","query","code","state","admin","custom","zitadel","issuerURL","clientId","callbackURL","cookieStore","code_verifier","get","pkce","value","response","fetch","URL","method","body","URLSearchParams","grant_type","redirect_uri","client_id","ok","id_token","json","set","name","idToken","sign","decode","httpOnly","path","sameSite","maxAge","secure","env","NODE_ENV","delete","redirect","Response","status","message"],"mappings":"AACA,SAAQA,OAAO,QAAO,kBAAiB;AACvC,OAAOC,aAAa,eAAc;AAClC,OAAOC,SAAS,eAAc;AAE9B,SAAQC,YAAY,QAAO,iBAAgB;AAC3C,SAAQC,OAAO,QAAO,kBAAiB;AAEvC,OAAO,MAAMC,WAA2B,OAAO,EACIC,SAAS,EAACC,MAAM,EAAEC,MAAM,EAAC,EACzBC,eAAe,EACfC,MAAM,EACNC,OAAO,EAACC,IAAI,EAAEC,KAAK,EAAC,EACvB;IAE5C,MAAM,EAACC,OAAO,EAACC,QAAQ,EAACC,SAAS,EAACC,SAAS,EAAEC,QAAQ,EAAEC,WAAW,EAAC,EAAC,EAAC,EAAC,GAAGZ;IAEzE,MAAMa,cAAcpB;IAEpB,MAAMqB,gBAAgBD,YAAYE,GAAG,CAAClB,QAAQmB,IAAI,GAAGC;IAErD,IAAIH,eAAe;QAEf,MAAMI,WAAW,MAAMC,MAAM,IAAIC,IAAI,CAAC,EAAEV,UAAU,eAAe,CAAC,GAAG;YACjEW,QAAQ;YACRC,MAAM,IAAIC,gBAAgB;gBACtBC,YAAY;gBACZnB,MAAMA;gBACNoB,cAAcb;gBACdc,WAAWf;gBACXG;YACJ;QACJ;QAEA,IAAII,SAASS,EAAE,EAAE;YAEb,MAAM,EAACC,QAAQ,EAAC,GAAG,MAAMV,SAASW,IAAI;YAEtC,IAAID,UAAU;gBAEVf,YAAYiB,GAAG,CAAC;oBACZC,MAAMlC,QAAQmC,OAAO;oBACrBf,OAAOtB,IAAIsC,IAAI,CAACtC,IAAIuC,MAAM,CAACN,WAA6B3B;oBACxDkC,UAAU;oBACVC,MAAM;oBACNC,UAAU;oBACVC,QAAQ;oBACRC,QAAQ7C,QAAQ8C,GAAG,CAACC,QAAQ,IAAI;gBACpC;gBACA5B,YAAY6B,MAAM,CAAC;gBAEnB,MAAMxB,WAAWtB,aAAa+C,QAAQ,CAAC,CAAC,EAAE,IAAIvB,IAAIR,aAAaT,MAAM,CAAC,YAAY,CAAC;gBACnFe,SAASzB,OAAO,CAACqC,GAAG,CAAC;oBACjBC,MAAMlC,QAAQS,KAAK;oBACnBW,OAAOX,SAAmB;oBAC1B6B,UAAU;oBACVC,MAAM;oBACNC,UAAU;oBACVC,QAAQ;oBACRC,QAAQ7C,QAAQ8C,GAAG,CAACC,QAAQ,IAAI;gBACpC;gBACA,OAAOvB;YAEX;YAEA,OAAO0B,SAASf,IAAI,CAAC;gBACjBgB,QAAQ;gBACRC,SAAS;YACb;QAEJ;QAEA,OAAOF,SAASf,IAAI,CAAC;YACjBgB,QAAQ;YACRC,SAAS;QACb;IAEJ;IAEA,OAAOF,SAASf,IAAI,CAAC;QACjBgB,QAAQ;QACRC,SAAS;IACb;AAEJ,EAAC"}
@@ -1,3 +1,4 @@
1
1
  export { authorize } from './authorize.js';
2
2
  export { callback } from './callback.js';
3
+ export { redirect } from './redirect.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AACtC,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA"}
@@ -1,4 +1,5 @@
1
1
  export { authorize } from './authorize.js';
2
2
  export { callback } from './callback.js';
3
+ export { redirect } from './redirect.js';
3
4
 
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/handlers/index.ts"],"sourcesContent":["export {authorize} from './authorize.js'\nexport {callback} from './callback.js'"],"names":["authorize","callback"],"mappings":"AAAA,SAAQA,SAAS,QAAO,iBAAgB;AACxC,SAAQC,QAAQ,QAAO,gBAAe"}
1
+ {"version":3,"sources":["../../src/handlers/index.ts"],"sourcesContent":["export {authorize} from './authorize.js'\nexport {callback} from './callback.js'\nexport {redirect} from './redirect.js'"],"names":["authorize","callback","redirect"],"mappings":"AAAA,SAAQA,SAAS,QAAO,iBAAgB;AACxC,SAAQC,QAAQ,QAAO,gBAAe;AACtC,SAAQC,QAAQ,QAAO,gBAAe"}
@@ -0,0 +1,4 @@
1
+ import { PayloadHandler } from 'payload';
2
+ import { ZitadelOnSuccess } from '../types.js';
3
+ export declare const redirect: (onSuccess: ZitadelOnSuccess) => PayloadHandler;
4
+ //# sourceMappingURL=redirect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redirect.d.ts","sourceRoot":"","sources":["../../src/handlers/redirect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,SAAS,CAAA;AAEtC,OAAO,EAAC,gBAAgB,EAAC,MAAM,aAAa,CAAA;AAG5C,eAAO,MAAM,QAAQ,cAAe,gBAAgB,KAAG,cAUtD,CAAA"}
@@ -0,0 +1,10 @@
1
+ import { cookies } from 'next/headers.js';
2
+ import { COOKIES } from '../constants.js';
3
+ export const redirect = (onSuccess)=>async ()=>{
4
+ const cookieStore = cookies();
5
+ const zitadelState = new URLSearchParams(atob(cookieStore.get(COOKIES.state)?.value ?? ''));
6
+ cookieStore.delete(COOKIES.state);
7
+ return onSuccess(zitadelState);
8
+ };
9
+
10
+ //# sourceMappingURL=redirect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/handlers/redirect.ts"],"sourcesContent":["import {PayloadHandler} from 'payload'\nimport {cookies} from 'next/headers.js'\nimport {ZitadelOnSuccess} from '../types.js'\nimport {COOKIES} from '../constants.js'\n\nexport const redirect = (onSuccess: ZitadelOnSuccess): PayloadHandler => async () => {\n\n const cookieStore = cookies()\n\n const zitadelState = new URLSearchParams(atob(cookieStore.get(COOKIES.state)?.value ?? ''))\n\n cookieStore.delete(COOKIES.state)\n\n return onSuccess(zitadelState)\n\n}"],"names":["cookies","COOKIES","redirect","onSuccess","cookieStore","zitadelState","URLSearchParams","atob","get","state","value","delete"],"mappings":"AACA,SAAQA,OAAO,QAAO,kBAAiB;AAEvC,SAAQC,OAAO,QAAO,kBAAiB;AAEvC,OAAO,MAAMC,WAAW,CAACC,YAAgD;QAErE,MAAMC,cAAcJ;QAEpB,MAAMK,eAAe,IAAIC,gBAAgBC,KAAKH,YAAYI,GAAG,CAACP,QAAQQ,KAAK,GAAGC,SAAS;QAEvFN,YAAYO,MAAM,CAACV,QAAQQ,KAAK;QAEhC,OAAON,UAAUE;IAErB,EAAC"}
@@ -1,5 +1,6 @@
1
- export declare const useCurrentUser: () => {
2
- user: any;
1
+ import { User } from 'payload';
2
+ export declare const useCurrentUser: <T extends User>() => {
3
+ user: T;
3
4
  isError: boolean;
4
5
  isLoading: boolean;
5
6
  };
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/hooks/user.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc;;;;CAU1B,CAAA"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/hooks/user.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,IAAI,EAAC,MAAM,SAAS,CAAA;AAE5B,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,IAAI;UAKvB,CAAC;;;CAKtB,CAAA"}
@@ -3,7 +3,7 @@ import { usePayloadAPI } from '@payloadcms/ui';
3
3
  export const useCurrentUser = ()=>{
4
4
  const { data: { user }, isError, isLoading } = usePayloadAPI('/api/users/me')[0];
5
5
  return {
6
- user,
6
+ user: user,
7
7
  isError,
8
8
  isLoading
9
9
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/hooks/user.ts"],"sourcesContent":["'use client'\n\nimport {usePayloadAPI} from '@payloadcms/ui'\n\nexport const useCurrentUser = () => {\n\n const {data: {user}, isError, isLoading} = usePayloadAPI('/api/users/me')[0]\n\n return {\n user,\n isError,\n isLoading\n }\n\n}"],"names":["usePayloadAPI","useCurrentUser","data","user","isError","isLoading"],"mappings":"AAAA;AAEA,SAAQA,aAAa,QAAO,iBAAgB;AAE5C,OAAO,MAAMC,iBAAiB;IAE1B,MAAM,EAACC,MAAM,EAACC,IAAI,EAAC,EAAEC,OAAO,EAAEC,SAAS,EAAC,GAAGL,cAAc,gBAAgB,CAAC,EAAE;IAE5E,OAAO;QACHG;QACAC;QACAC;IACJ;AAEJ,EAAC"}
1
+ {"version":3,"sources":["../../src/hooks/user.ts"],"sourcesContent":["'use client'\n\nimport {usePayloadAPI} from '@payloadcms/ui'\nimport {User} from 'payload'\n\nexport const useCurrentUser = <T extends User>() => {\n\n const {data: {user}, isError, isLoading} = usePayloadAPI('/api/users/me')[0]\n\n return {\n user: user as T,\n isError,\n isLoading\n }\n\n}"],"names":["usePayloadAPI","useCurrentUser","data","user","isError","isLoading"],"mappings":"AAAA;AAEA,SAAQA,aAAa,QAAO,iBAAgB;AAG5C,OAAO,MAAMC,iBAAiB;IAE1B,MAAM,EAACC,MAAM,EAACC,IAAI,EAAC,EAAEC,OAAO,EAAEC,SAAS,EAAC,GAAGL,cAAc,gBAAgB,CAAC,EAAE;IAE5E,OAAO;QACHG,MAAMA;QACNC;QACAC;IACJ;AAEJ,EAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAA6C,iBAAiB,EAAC,MAAM,YAAY,CAAA;AAIxF,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,eAAO,MAAM,aAAa,EAAE,iBAsM3B,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAA6C,iBAAiB,EAAC,MAAM,YAAY,CAAA;AAIxF,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,eAAO,MAAM,aAAa,EAAE,iBA0M3B,CAAA"}
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { cookies } from 'next/headers.js';
2
2
  import { Avatar, LoginButton } from './components/index.js';
3
- import { COOKIE_ID_TOKEN, DEFAULT_CONFIG, DELETE_ME_USER, ERROR_MESSAGES, ROUTES } from './constants.js';
4
- import { authorize, callback } from './handlers/index.js';
3
+ import { COOKIES, DEFAULT_CONFIG, DELETE_ME_USER, ERROR_MESSAGES, ROUTES } from './constants.js';
4
+ import { authorize, callback, redirect } from './handlers/index.js';
5
5
  import { zitadelStrategy } from './strategy.js';
6
6
  import { translations } from './translations.js';
7
7
  import { NextResponse } from 'next/server.js';
@@ -18,10 +18,7 @@ export const ZitadelPlugin = ({ associatedIdFieldName = DEFAULT_CONFIG.associate
18
18
  const serverURL = incomingConfig.serverURL ?? 'http://localhost';
19
19
  const authSlug = incomingConfig.admin?.user ?? 'users';
20
20
  const authBaseURL = `${serverURL}/api/${authSlug}`;
21
- const defaultOnSuccess = (state)=>NextResponse.redirect([
22
- serverURL,
23
- state.get('redirect')
24
- ].join(''));
21
+ const defaultOnSuccess = (state)=>NextResponse.redirect(serverURL + (state.get('redirect') ?? ''));
25
22
  return {
26
23
  ...incomingConfig,
27
24
  admin: {
@@ -77,7 +74,7 @@ export const ZitadelPlugin = ({ associatedIdFieldName = DEFAULT_CONFIG.associate
77
74
  },
78
75
  hooks: {
79
76
  afterLogout: [
80
- ()=>cookies().delete(COOKIE_ID_TOKEN)
77
+ ()=>cookies().delete(COOKIES.idToken)
81
78
  ],
82
79
  // current work around (see onInit)
83
80
  afterChange: [
@@ -108,7 +105,12 @@ export const ZitadelPlugin = ({ associatedIdFieldName = DEFAULT_CONFIG.associate
108
105
  {
109
106
  path: ROUTES.callback,
110
107
  method: 'get',
111
- handler: callback(onSuccess ?? defaultOnSuccess)
108
+ handler: callback
109
+ },
110
+ {
111
+ path: ROUTES.redirect,
112
+ method: 'get',
113
+ handler: redirect(onSuccess ?? defaultOnSuccess)
112
114
  }
113
115
  ],
114
116
  fields: [
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {cookies} from 'next/headers.js'\nimport {Avatar, LoginButton} from './components/index.js'\nimport {COOKIE_ID_TOKEN, DEFAULT_CONFIG, DELETE_ME_USER, ERROR_MESSAGES, ROUTES} from './constants.js'\nimport {authorize, callback} from './handlers/index.js'\nimport {zitadelStrategy} from './strategy.js'\nimport {PayloadConfigWithZitadel, ZitadelOnSuccess, ZitadelPluginType} from './types.js'\nimport {translations} from './translations.js'\nimport {NextResponse} from 'next/server.js'\n\nexport {getCurrentUser} from './utils/index.js'\n\nexport const ZitadelPlugin: ZitadelPluginType = ({\n associatedIdFieldName = DEFAULT_CONFIG.associatedIdFieldName,\n disableAvatar,\n disableDefaultLoginButton,\n strategyName = DEFAULT_CONFIG.strategyName,\n label = DEFAULT_CONFIG.label,\n issuerURL,\n clientId,\n enableAPI,\n apiClientId,\n apiKeyId,\n apiKey,\n onSuccess\n }) => {\n\n if (!issuerURL)\n throw new Error(ERROR_MESSAGES.issuerURL)\n if (!clientId)\n throw new Error(ERROR_MESSAGES.clientId)\n if (enableAPI) {\n if (!apiClientId)\n throw new Error(ERROR_MESSAGES.apiClientId)\n if (!apiKeyId)\n throw new Error(ERROR_MESSAGES.apiKey)\n if (!apiKey)\n throw new Error(ERROR_MESSAGES.apiKey)\n }\n\n return (incomingConfig) => {\n\n const serverURL = incomingConfig.serverURL ?? 'http://localhost'\n\n const authSlug = incomingConfig.admin?.user ?? 'users'\n\n const authBaseURL = `${serverURL}/api/${authSlug}`\n\n const defaultOnSuccess: ZitadelOnSuccess = (state) =>\n NextResponse.redirect([serverURL, state.get('redirect')].join(''))\n\n return {\n ...incomingConfig,\n admin: {\n ...incomingConfig.admin,\n ...(disableAvatar ? {} : {avatar: Avatar}),\n components: {\n ...incomingConfig.admin?.components,\n afterLogin: [\n ...incomingConfig.admin?.components?.afterLogin || [],\n ...(disableDefaultLoginButton ? [] : [LoginButton])\n ]\n },\n custom: {\n zitadel: {\n issuerURL,\n clientId,\n label,\n authorizeURL: authBaseURL + ROUTES.authorize,\n callbackURL: authBaseURL + ROUTES.callback\n }\n }\n },\n collections: (incomingConfig.collections || []).map((collection) => {\n\n const authConfig = typeof collection.auth == 'boolean' ? {} : collection.auth\n\n return {\n ...collection,\n ...collection.slug == authSlug ? {\n auth: {\n ...authConfig,\n disableLocalStrategy: true,\n strategies: [\n ...authConfig?.strategies ?? [],\n zitadelStrategy({\n authSlug,\n associatedIdFieldName,\n strategyName: strategyName,\n issuerURL: issuerURL as string,\n clientId: clientId as string,\n ...(enableAPI ? {\n enableAPI: true,\n apiClientId: apiClientId!,\n apiKeyId: apiClientId!,\n apiKey: apiKey!\n } : {enableAPI: undefined})\n })\n ]\n },\n hooks: {\n\n afterLogout: [() => cookies().delete(COOKIE_ID_TOKEN)],\n\n // current work around (see onInit)\n afterChange: [async ({req}) => {\n const response = await req.payload.find({collection: authSlug})\n // to minimize unnecessary checks after the first two real users\n if (response.totalDocs == 2) {\n await req.payload.delete({\n collection: authSlug,\n where: {\n [associatedIdFieldName]: {\n equals: DELETE_ME_USER.associatedId\n }\n }\n })\n }\n }]\n\n },\n endpoints: [\n {\n path: ROUTES.authorize,\n method: 'get',\n handler: authorize\n },\n {\n path: ROUTES.callback,\n method: 'get',\n handler: callback(onSuccess ?? defaultOnSuccess)\n }\n ],\n fields: [\n ...collection.fields,\n {\n name: associatedIdFieldName,\n type: 'text',\n admin: {\n readOnly: true\n },\n unique: true,\n required: true\n },\n {\n name: 'email',\n type: 'email',\n admin: {\n readOnly: true\n }\n },\n {\n name: 'name',\n type: 'text',\n admin: {\n readOnly: true\n }\n },\n {\n name: 'image',\n type: 'text',\n admin: {\n readOnly: true\n }\n }\n ]\n } : {}\n }\n }),\n\n // current work around on creating a non-functional first user, which will be deleted after first login\n async onInit(payload) {\n if (incomingConfig.onInit)\n await incomingConfig.onInit(payload)\n\n const existingUsers = await payload.find({\n collection: authSlug,\n limit: 1\n })\n\n if (existingUsers.docs.length === 0) {\n await payload.create({\n collection: authSlug,\n data: {\n email: DELETE_ME_USER.email,\n password: DELETE_ME_USER.password,\n [associatedIdFieldName]: DELETE_ME_USER.associatedId\n }\n })\n }\n },\n\n i18n: {\n ...incomingConfig.i18n,\n translations: {\n ...incomingConfig.i18n?.translations,\n de: {\n ...incomingConfig.i18n?.translations?.de,\n ...translations.de\n },\n en: {\n ...incomingConfig.i18n?.translations?.en,\n ...translations.en\n }\n }\n }\n } satisfies PayloadConfigWithZitadel\n\n }\n\n}"],"names":["cookies","Avatar","LoginButton","COOKIE_ID_TOKEN","DEFAULT_CONFIG","DELETE_ME_USER","ERROR_MESSAGES","ROUTES","authorize","callback","zitadelStrategy","translations","NextResponse","getCurrentUser","ZitadelPlugin","associatedIdFieldName","disableAvatar","disableDefaultLoginButton","strategyName","label","issuerURL","clientId","enableAPI","apiClientId","apiKeyId","apiKey","onSuccess","Error","incomingConfig","serverURL","authSlug","admin","user","authBaseURL","defaultOnSuccess","state","redirect","get","join","avatar","components","afterLogin","custom","zitadel","authorizeURL","callbackURL","collections","map","collection","authConfig","auth","slug","disableLocalStrategy","strategies","undefined","hooks","afterLogout","delete","afterChange","req","response","payload","find","totalDocs","where","equals","associatedId","endpoints","path","method","handler","fields","name","type","readOnly","unique","required","onInit","existingUsers","limit","docs","length","create","data","email","password","i18n","de","en"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["import {cookies} from 'next/headers.js'\nimport {Avatar, LoginButton} from './components/index.js'\nimport {COOKIES, DEFAULT_CONFIG, DELETE_ME_USER, ERROR_MESSAGES, ROUTES} from './constants.js'\nimport {authorize, callback, redirect} from './handlers/index.js'\nimport {zitadelStrategy} from './strategy.js'\nimport {PayloadConfigWithZitadel, ZitadelOnSuccess, ZitadelPluginType} from './types.js'\nimport {translations} from './translations.js'\nimport {NextResponse} from 'next/server.js'\n\nexport {getCurrentUser} from './utils/index.js'\n\nexport const ZitadelPlugin: ZitadelPluginType = ({\n associatedIdFieldName = DEFAULT_CONFIG.associatedIdFieldName,\n disableAvatar,\n disableDefaultLoginButton,\n strategyName = DEFAULT_CONFIG.strategyName,\n label = DEFAULT_CONFIG.label,\n issuerURL,\n clientId,\n enableAPI,\n apiClientId,\n apiKeyId,\n apiKey,\n onSuccess\n }) => {\n\n if (!issuerURL)\n throw new Error(ERROR_MESSAGES.issuerURL)\n if (!clientId)\n throw new Error(ERROR_MESSAGES.clientId)\n if (enableAPI) {\n if (!apiClientId)\n throw new Error(ERROR_MESSAGES.apiClientId)\n if (!apiKeyId)\n throw new Error(ERROR_MESSAGES.apiKey)\n if (!apiKey)\n throw new Error(ERROR_MESSAGES.apiKey)\n }\n\n return (incomingConfig) => {\n\n const serverURL = incomingConfig.serverURL ?? 'http://localhost'\n\n const authSlug = incomingConfig.admin?.user ?? 'users'\n\n const authBaseURL = `${serverURL}/api/${authSlug}`\n\n const defaultOnSuccess: ZitadelOnSuccess = (state) =>\n NextResponse.redirect(serverURL + (state.get('redirect') ?? ''))\n\n return {\n ...incomingConfig,\n admin: {\n ...incomingConfig.admin,\n ...(disableAvatar ? {} : {avatar: Avatar}),\n components: {\n ...incomingConfig.admin?.components,\n afterLogin: [\n ...incomingConfig.admin?.components?.afterLogin || [],\n ...(disableDefaultLoginButton ? [] : [LoginButton])\n ]\n },\n custom: {\n zitadel: {\n issuerURL,\n clientId,\n label,\n authorizeURL: authBaseURL + ROUTES.authorize,\n callbackURL: authBaseURL + ROUTES.callback\n }\n }\n },\n collections: (incomingConfig.collections || []).map((collection) => {\n\n const authConfig = typeof collection.auth == 'boolean' ? {} : collection.auth\n\n return {\n ...collection,\n ...collection.slug == authSlug ? {\n auth: {\n ...authConfig,\n disableLocalStrategy: true,\n strategies: [\n ...authConfig?.strategies ?? [],\n zitadelStrategy({\n authSlug,\n associatedIdFieldName,\n strategyName: strategyName,\n issuerURL: issuerURL as string,\n clientId: clientId as string,\n ...(enableAPI ? {\n enableAPI: true,\n apiClientId: apiClientId!,\n apiKeyId: apiClientId!,\n apiKey: apiKey!\n } : {enableAPI: undefined})\n })\n ]\n },\n hooks: {\n afterLogout: [() => cookies().delete(COOKIES.idToken)],\n\n // current work around (see onInit)\n afterChange: [async ({req}) => {\n const response = await req.payload.find({collection: authSlug})\n // to minimize unnecessary checks after the first two real users\n if (response.totalDocs == 2) {\n await req.payload.delete({\n collection: authSlug,\n where: {\n [associatedIdFieldName]: {\n equals: DELETE_ME_USER.associatedId\n }\n }\n })\n }\n }]\n\n },\n endpoints: [\n {\n path: ROUTES.authorize,\n method: 'get',\n handler: authorize\n },\n {\n path: ROUTES.callback,\n method: 'get',\n handler: callback\n },\n {\n path: ROUTES.redirect,\n method: 'get',\n handler: redirect(onSuccess ?? defaultOnSuccess)\n }\n ],\n fields: [\n ...collection.fields,\n {\n name: associatedIdFieldName,\n type: 'text',\n admin: {\n readOnly: true\n },\n unique: true,\n required: true\n },\n {\n name: 'email',\n type: 'email',\n admin: {\n readOnly: true\n }\n },\n {\n name: 'name',\n type: 'text',\n admin: {\n readOnly: true\n }\n },\n {\n name: 'image',\n type: 'text',\n admin: {\n readOnly: true\n }\n }\n ]\n } : {}\n }\n }),\n\n // current work around on creating a non-functional first user, which will be deleted after first login\n async onInit(payload) {\n if (incomingConfig.onInit)\n await incomingConfig.onInit(payload)\n\n const existingUsers = await payload.find({\n collection: authSlug,\n limit: 1\n })\n\n if (existingUsers.docs.length === 0) {\n await payload.create({\n collection: authSlug,\n data: {\n email: DELETE_ME_USER.email,\n password: DELETE_ME_USER.password,\n [associatedIdFieldName]: DELETE_ME_USER.associatedId\n }\n })\n }\n },\n\n i18n: {\n ...incomingConfig.i18n,\n translations: {\n ...incomingConfig.i18n?.translations,\n de: {\n ...incomingConfig.i18n?.translations?.de,\n ...translations.de\n },\n en: {\n ...incomingConfig.i18n?.translations?.en,\n ...translations.en\n }\n }\n }\n } satisfies PayloadConfigWithZitadel\n\n }\n\n}"],"names":["cookies","Avatar","LoginButton","COOKIES","DEFAULT_CONFIG","DELETE_ME_USER","ERROR_MESSAGES","ROUTES","authorize","callback","redirect","zitadelStrategy","translations","NextResponse","getCurrentUser","ZitadelPlugin","associatedIdFieldName","disableAvatar","disableDefaultLoginButton","strategyName","label","issuerURL","clientId","enableAPI","apiClientId","apiKeyId","apiKey","onSuccess","Error","incomingConfig","serverURL","authSlug","admin","user","authBaseURL","defaultOnSuccess","state","get","avatar","components","afterLogin","custom","zitadel","authorizeURL","callbackURL","collections","map","collection","authConfig","auth","slug","disableLocalStrategy","strategies","undefined","hooks","afterLogout","delete","idToken","afterChange","req","response","payload","find","totalDocs","where","equals","associatedId","endpoints","path","method","handler","fields","name","type","readOnly","unique","required","onInit","existingUsers","limit","docs","length","create","data","email","password","i18n","de","en"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,mBAAmB,EAAC,MAAM,YAAY,CAAA;AAI9D,eAAO,MAAM,eAAe,EAAE,mBA6F5B,CAAA"}
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../src/strategy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,mBAAmB,EAAC,MAAM,YAAY,CAAA;AAK9D,eAAO,MAAM,eAAe,EAAE,mBA6F5B,CAAA"}
package/dist/strategy.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import jwt from 'jsonwebtoken';
2
2
  import { cookies } from 'next/headers.js';
3
+ import { COOKIES } from './constants.js';
3
4
  export const zitadelStrategy = ({ authSlug, associatedIdFieldName, strategyName, issuerURL, enableAPI, apiClientId, apiKeyId, apiKey })=>({
4
5
  name: strategyName,
5
6
  authenticate: async ({ headers, payload })=>{
@@ -36,8 +37,8 @@ export const zitadelStrategy = ({ authSlug, associatedIdFieldName, strategyName,
36
37
  }
37
38
  }
38
39
  // in case of normal browsing
39
- if (!idp_id && cookieStore.has('id_token')) {
40
- id_token = jwt.verify(cookieStore.get('id_token')?.value ?? '', payload.config.secret);
40
+ if (!idp_id && cookieStore.has(COOKIES.idToken)) {
41
+ id_token = jwt.verify(cookieStore.get(COOKIES.idToken)?.value ?? '', payload.secret);
41
42
  idp_id = id_token.sub;
42
43
  }
43
44
  // search for associated user; if not found, create one
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/strategy.ts"],"sourcesContent":["import {ZitadelIdToken, ZitadelStrategyType} from './types.js'\nimport jwt from 'jsonwebtoken'\nimport {cookies} from 'next/headers.js'\n\nexport const zitadelStrategy: ZitadelStrategyType = ({\n authSlug,\n associatedIdFieldName,\n strategyName,\n issuerURL,\n enableAPI,\n apiClientId,\n apiKeyId,\n apiKey\n }) => ({\n name: strategyName,\n authenticate: async ({headers, payload}) => {\n\n let id, idp_id, id_token\n\n const cookieStore = cookies()\n\n if (enableAPI) {\n // in case of incoming API call from the app\n const authHeader = headers.get('Authorization')\n if (authHeader?.includes('Bearer')) {\n const introspect = await fetch(`${issuerURL}/oauth/v2/introspect`, {\n method: 'post',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams({\n 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n 'client_assertion': jwt.sign({}, apiKey, {\n algorithm: 'RS256',\n audience: issuerURL,\n expiresIn: '1h',\n issuer: apiClientId,\n keyid: apiKeyId,\n subject: apiClientId\n }),\n 'token': authHeader.split(' ')[1]\n })\n })\n if (introspect.ok) {\n const data = await introspect.json()\n if (data?.active) {\n idp_id = data.sub\n }\n }\n }\n }\n\n // in case of normal browsing\n if (!idp_id && cookieStore.has('id_token')) {\n id_token = jwt.verify(cookieStore.get('id_token')?.value ?? '', payload.config.secret) as ZitadelIdToken\n idp_id = id_token.sub\n }\n\n // search for associated user; if not found, create one\n if (idp_id) {\n const {docs} = await payload.find({\n collection: authSlug,\n where: {\n [associatedIdFieldName]: {\n equals: idp_id\n }\n }\n })\n id = docs.length ? docs[0].id : (await payload.create({\n collection: authSlug,\n data: {\n [associatedIdFieldName]: idp_id\n }\n })).id\n }\n\n // update user information if possible\n if (id && id_token) {\n await payload.update({\n collection: authSlug,\n id,\n data: {\n email: id_token.email,\n name: id_token.name,\n image: id_token.picture\n }\n })\n }\n\n return {\n user: id ? {\n collection: authSlug,\n id\n } : null\n }\n\n }\n})"],"names":["jwt","cookies","zitadelStrategy","authSlug","associatedIdFieldName","strategyName","issuerURL","enableAPI","apiClientId","apiKeyId","apiKey","name","authenticate","headers","payload","id","idp_id","id_token","cookieStore","authHeader","get","includes","introspect","fetch","method","body","URLSearchParams","sign","algorithm","audience","expiresIn","issuer","keyid","subject","split","ok","data","json","active","sub","has","verify","value","config","secret","docs","find","collection","where","equals","length","create","update","email","image","picture","user"],"mappings":"AACA,OAAOA,SAAS,eAAc;AAC9B,SAAQC,OAAO,QAAO,kBAAiB;AAEvC,OAAO,MAAMC,kBAAuC,CAAC,EACIC,QAAQ,EACRC,qBAAqB,EACrBC,YAAY,EACZC,SAAS,EACTC,SAAS,EACTC,WAAW,EACXC,QAAQ,EACRC,MAAM,EACT,GAAM,CAAA;QACxDC,MAAMN;QACNO,cAAc,OAAO,EAACC,OAAO,EAAEC,OAAO,EAAC;YAEnC,IAAIC,IAAIC,QAAQC;YAEhB,MAAMC,cAAcjB;YAEpB,IAAIM,WAAW;gBACX,4CAA4C;gBAC5C,MAAMY,aAAaN,QAAQO,GAAG,CAAC;gBAC/B,IAAID,YAAYE,SAAS,WAAW;oBAChC,MAAMC,aAAa,MAAMC,MAAM,CAAC,EAAEjB,UAAU,oBAAoB,CAAC,EAAE;wBAC/DkB,QAAQ;wBACRX,SAAS;4BACL,gBAAgB;wBACpB;wBACAY,MAAM,IAAIC,gBAAgB;4BACtB,yBAAyB;4BACzB,oBAAoB1B,IAAI2B,IAAI,CAAC,CAAC,GAAGjB,QAAQ;gCACrCkB,WAAW;gCACXC,UAAUvB;gCACVwB,WAAW;gCACXC,QAAQvB;gCACRwB,OAAOvB;gCACPwB,SAASzB;4BACb;4BACA,SAASW,WAAWe,KAAK,CAAC,IAAI,CAAC,EAAE;wBACrC;oBACJ;oBACA,IAAIZ,WAAWa,EAAE,EAAE;wBACf,MAAMC,OAAO,MAAMd,WAAWe,IAAI;wBAClC,IAAID,MAAME,QAAQ;4BACdtB,SAASoB,KAAKG,GAAG;wBACrB;oBACJ;gBACJ;YACJ;YAEA,6BAA6B;YAC7B,IAAI,CAACvB,UAAUE,YAAYsB,GAAG,CAAC,aAAa;gBACxCvB,WAAWjB,IAAIyC,MAAM,CAACvB,YAAYE,GAAG,CAAC,aAAasB,SAAS,IAAI5B,QAAQ6B,MAAM,CAACC,MAAM;gBACrF5B,SAASC,SAASsB,GAAG;YACzB;YAEA,uDAAuD;YACvD,IAAIvB,QAAQ;gBACR,MAAM,EAAC6B,IAAI,EAAC,GAAG,MAAM/B,QAAQgC,IAAI,CAAC;oBAC9BC,YAAY5C;oBACZ6C,OAAO;wBACH,CAAC5C,sBAAsB,EAAE;4BACrB6C,QAAQjC;wBACZ;oBACJ;gBACJ;gBACAD,KAAK8B,KAAKK,MAAM,GAAGL,IAAI,CAAC,EAAE,CAAC9B,EAAE,GAAG,AAAC,CAAA,MAAMD,QAAQqC,MAAM,CAAC;oBAClDJ,YAAY5C;oBACZiC,MAAM;wBACF,CAAChC,sBAAsB,EAAEY;oBAC7B;gBACJ,EAAC,EAAGD,EAAE;YACV;YAEA,sCAAsC;YACtC,IAAIA,MAAME,UAAU;gBAChB,MAAMH,QAAQsC,MAAM,CAAC;oBACjBL,YAAY5C;oBACZY;oBACAqB,MAAM;wBACFiB,OAAOpC,SAASoC,KAAK;wBACrB1C,MAAMM,SAASN,IAAI;wBACnB2C,OAAOrC,SAASsC,OAAO;oBAC3B;gBACJ;YACJ;YAEA,OAAO;gBACHC,MAAMzC,KAAK;oBACPgC,YAAY5C;oBACZY;gBACJ,IAAI;YACR;QAEJ;IACJ,CAAA,EAAE"}
1
+ {"version":3,"sources":["../src/strategy.ts"],"sourcesContent":["import {ZitadelIdToken, ZitadelStrategyType} from './types.js'\nimport jwt from 'jsonwebtoken'\nimport {cookies} from 'next/headers.js'\nimport {COOKIES} from './constants.js'\n\nexport const zitadelStrategy: ZitadelStrategyType = ({\n authSlug,\n associatedIdFieldName,\n strategyName,\n issuerURL,\n enableAPI,\n apiClientId,\n apiKeyId,\n apiKey\n }) => ({\n name: strategyName,\n authenticate: async ({headers, payload}) => {\n\n let id, idp_id, id_token\n\n const cookieStore = cookies()\n\n if (enableAPI) {\n // in case of incoming API call from the app\n const authHeader = headers.get('Authorization')\n if (authHeader?.includes('Bearer')) {\n const introspect = await fetch(`${issuerURL}/oauth/v2/introspect`, {\n method: 'post',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n },\n body: new URLSearchParams({\n 'client_assertion_type': 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',\n 'client_assertion': jwt.sign({}, apiKey, {\n algorithm: 'RS256',\n audience: issuerURL,\n expiresIn: '1h',\n issuer: apiClientId,\n keyid: apiKeyId,\n subject: apiClientId\n }),\n 'token': authHeader.split(' ')[1]\n })\n })\n if (introspect.ok) {\n const data = await introspect.json()\n if (data?.active) {\n idp_id = data.sub\n }\n }\n }\n }\n\n // in case of normal browsing\n if (!idp_id && cookieStore.has(COOKIES.idToken)) {\n id_token = jwt.verify(cookieStore.get(COOKIES.idToken)?.value ?? '', payload.secret) as ZitadelIdToken\n idp_id = id_token.sub\n }\n\n // search for associated user; if not found, create one\n if (idp_id) {\n const {docs} = await payload.find({\n collection: authSlug,\n where: {\n [associatedIdFieldName]: {\n equals: idp_id\n }\n }\n })\n id = docs.length ? docs[0].id : (await payload.create({\n collection: authSlug,\n data: {\n [associatedIdFieldName]: idp_id\n }\n })).id\n }\n\n // update user information if possible\n if (id && id_token) {\n await payload.update({\n collection: authSlug,\n id,\n data: {\n email: id_token.email,\n name: id_token.name,\n image: id_token.picture\n }\n })\n }\n\n return {\n user: id ? {\n collection: authSlug,\n id\n } : null\n }\n\n }\n})"],"names":["jwt","cookies","COOKIES","zitadelStrategy","authSlug","associatedIdFieldName","strategyName","issuerURL","enableAPI","apiClientId","apiKeyId","apiKey","name","authenticate","headers","payload","id","idp_id","id_token","cookieStore","authHeader","get","includes","introspect","fetch","method","body","URLSearchParams","sign","algorithm","audience","expiresIn","issuer","keyid","subject","split","ok","data","json","active","sub","has","idToken","verify","value","secret","docs","find","collection","where","equals","length","create","update","email","image","picture","user"],"mappings":"AACA,OAAOA,SAAS,eAAc;AAC9B,SAAQC,OAAO,QAAO,kBAAiB;AACvC,SAAQC,OAAO,QAAO,iBAAgB;AAEtC,OAAO,MAAMC,kBAAuC,CAAC,EACIC,QAAQ,EACRC,qBAAqB,EACrBC,YAAY,EACZC,SAAS,EACTC,SAAS,EACTC,WAAW,EACXC,QAAQ,EACRC,MAAM,EACT,GAAM,CAAA;QACxDC,MAAMN;QACNO,cAAc,OAAO,EAACC,OAAO,EAAEC,OAAO,EAAC;YAEnC,IAAIC,IAAIC,QAAQC;YAEhB,MAAMC,cAAclB;YAEpB,IAAIO,WAAW;gBACX,4CAA4C;gBAC5C,MAAMY,aAAaN,QAAQO,GAAG,CAAC;gBAC/B,IAAID,YAAYE,SAAS,WAAW;oBAChC,MAAMC,aAAa,MAAMC,MAAM,CAAC,EAAEjB,UAAU,oBAAoB,CAAC,EAAE;wBAC/DkB,QAAQ;wBACRX,SAAS;4BACL,gBAAgB;wBACpB;wBACAY,MAAM,IAAIC,gBAAgB;4BACtB,yBAAyB;4BACzB,oBAAoB3B,IAAI4B,IAAI,CAAC,CAAC,GAAGjB,QAAQ;gCACrCkB,WAAW;gCACXC,UAAUvB;gCACVwB,WAAW;gCACXC,QAAQvB;gCACRwB,OAAOvB;gCACPwB,SAASzB;4BACb;4BACA,SAASW,WAAWe,KAAK,CAAC,IAAI,CAAC,EAAE;wBACrC;oBACJ;oBACA,IAAIZ,WAAWa,EAAE,EAAE;wBACf,MAAMC,OAAO,MAAMd,WAAWe,IAAI;wBAClC,IAAID,MAAME,QAAQ;4BACdtB,SAASoB,KAAKG,GAAG;wBACrB;oBACJ;gBACJ;YACJ;YAEA,6BAA6B;YAC7B,IAAI,CAACvB,UAAUE,YAAYsB,GAAG,CAACvC,QAAQwC,OAAO,GAAG;gBAC7CxB,WAAWlB,IAAI2C,MAAM,CAACxB,YAAYE,GAAG,CAACnB,QAAQwC,OAAO,GAAGE,SAAS,IAAI7B,QAAQ8B,MAAM;gBACnF5B,SAASC,SAASsB,GAAG;YACzB;YAEA,uDAAuD;YACvD,IAAIvB,QAAQ;gBACR,MAAM,EAAC6B,IAAI,EAAC,GAAG,MAAM/B,QAAQgC,IAAI,CAAC;oBAC9BC,YAAY5C;oBACZ6C,OAAO;wBACH,CAAC5C,sBAAsB,EAAE;4BACrB6C,QAAQjC;wBACZ;oBACJ;gBACJ;gBACAD,KAAK8B,KAAKK,MAAM,GAAGL,IAAI,CAAC,EAAE,CAAC9B,EAAE,GAAG,AAAC,CAAA,MAAMD,QAAQqC,MAAM,CAAC;oBAClDJ,YAAY5C;oBACZiC,MAAM;wBACF,CAAChC,sBAAsB,EAAEY;oBAC7B;gBACJ,EAAC,EAAGD,EAAE;YACV;YAEA,sCAAsC;YACtC,IAAIA,MAAME,UAAU;gBAChB,MAAMH,QAAQsC,MAAM,CAAC;oBACjBL,YAAY5C;oBACZY;oBACAqB,MAAM;wBACFiB,OAAOpC,SAASoC,KAAK;wBACrB1C,MAAMM,SAASN,IAAI;wBACnB2C,OAAOrC,SAASsC,OAAO;oBAC3B;gBACJ;YACJ;YAEA,OAAO;gBACHC,MAAMzC,KAAK;oBACPgC,YAAY5C;oBACZY;gBACJ,IAAI;YACR;QAEJ;IACJ,CAAA,EAAE"}
@@ -1,5 +1,5 @@
1
- import { SanitizedConfig } from 'payload';
2
- export declare const getCurrentUser: ({ config }: {
1
+ import { SanitizedConfig, User } from 'payload';
2
+ export declare const getCurrentUser: <T extends User>({ config }: {
3
3
  config: Promise<SanitizedConfig>;
4
- }) => Promise<(Record<string, unknown> & import("payload").TypeWithID) | null>;
4
+ }) => Promise<T | null>;
5
5
  //# sourceMappingURL=user.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/utils/user.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAC,MAAM,SAAS,CAAA;AAEvC,eAAO,MAAM,cAAc,eAAoB;IAAE,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;CAAE,6EAQlF,CAAA"}
1
+ {"version":3,"file":"user.d.ts","sourceRoot":"","sources":["../../src/utils/user.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,eAAe,EAAE,IAAI,EAAC,MAAM,SAAS,CAAA;AAE7C,eAAO,MAAM,cAAc,GAAU,CAAC,SAAS,IAAI,cAAY;IAAE,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;CAAE,sBAQlG,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/user.ts"],"sourcesContent":["import {getPayloadHMR} from '@payloadcms/next/utilities'\nimport {headers} from 'next/headers.js'\nimport {SanitizedConfig} from 'payload'\n\nexport const getCurrentUser = async ({config}: { config: Promise<SanitizedConfig> }) => {\n\n const payload = await getPayloadHMR({config})\n\n const {user} = await payload.auth({headers: headers()})\n\n return user ? await payload.findByID({...user}) : null\n\n}"],"names":["getPayloadHMR","headers","getCurrentUser","config","payload","user","auth","findByID"],"mappings":"AAAA,SAAQA,aAAa,QAAO,6BAA4B;AACxD,SAAQC,OAAO,QAAO,kBAAiB;AAGvC,OAAO,MAAMC,iBAAiB,OAAO,EAACC,MAAM,EAAuC;IAE/E,MAAMC,UAAU,MAAMJ,cAAc;QAACG;IAAM;IAE3C,MAAM,EAACE,IAAI,EAAC,GAAG,MAAMD,QAAQE,IAAI,CAAC;QAACL,SAASA;IAAS;IAErD,OAAOI,OAAO,MAAMD,QAAQG,QAAQ,CAAC;QAAC,GAAGF,IAAI;IAAA,KAAK;AAEtD,EAAC"}
1
+ {"version":3,"sources":["../../src/utils/user.ts"],"sourcesContent":["import {getPayloadHMR} from '@payloadcms/next/utilities'\nimport {headers} from 'next/headers.js'\nimport {SanitizedConfig, User} from 'payload'\n\nexport const getCurrentUser = async <T extends User>({config}: { config: Promise<SanitizedConfig> }) => {\n\n const payload = await getPayloadHMR({config})\n\n const {user} = await payload.auth({headers: headers()})\n\n return user ? (await payload.findByID({...user})) as T : null\n\n}"],"names":["getPayloadHMR","headers","getCurrentUser","config","payload","user","auth","findByID"],"mappings":"AAAA,SAAQA,aAAa,QAAO,6BAA4B;AACxD,SAAQC,OAAO,QAAO,kBAAiB;AAGvC,OAAO,MAAMC,iBAAiB,OAAuB,EAACC,MAAM,EAAuC;IAE/F,MAAMC,UAAU,MAAMJ,cAAc;QAACG;IAAM;IAE3C,MAAM,EAACE,IAAI,EAAC,GAAG,MAAMD,QAAQE,IAAI,CAAC;QAACL,SAASA;IAAS;IAErD,OAAOI,OAAQ,MAAMD,QAAQG,QAAQ,CAAC;QAAC,GAAGF,IAAI;IAAA,KAAW;AAE7D,EAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-zitadel-plugin",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "plugin for Payload CMS, which enables authentication via Zitadel IdP",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -36,24 +36,24 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@payloadcms/next": "3.0.0-beta.67",
40
- "@payloadcms/translations": "3.0.0-beta.67",
41
- "@payloadcms/ui": "3.0.0-beta.67",
39
+ "@payloadcms/next": "3.0.0-beta.68",
40
+ "@payloadcms/translations": "3.0.0-beta.68",
41
+ "@payloadcms/ui": "3.0.0-beta.68",
42
42
  "jsonwebtoken": "^9.0.2",
43
- "next": "^15.0.0-canary.74",
44
- "payload": "3.0.0-beta.67",
43
+ "next": "^15.0.0-canary.83",
44
+ "payload": "3.0.0-beta.68",
45
45
  "react": "rc",
46
46
  "react-dom": "rc"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@swc/cli": "^0.4.0",
50
- "@swc/core": "^1.7.0",
50
+ "@swc/core": "^1.7.2",
51
51
  "@types/jsonwebtoken": "^9.0.6",
52
- "@types/node": "^20.14.11",
52
+ "@types/node": "^20.14.12",
53
53
  "@types/react": "^18.3.3",
54
54
  "@types/react-dom": "^18.3.0",
55
55
  "rimraf": "^6.0.1",
56
- "typescript": "^5.5.3"
56
+ "typescript": "^5.5.4"
57
57
  },
58
58
  "engines": {
59
59
  "node": "^22.5.1"