@opensaas/keystone-nextjs-auth 22.0.0 → 22.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # @opensaas-keystone/nextjs-auth
2
2
 
3
+ ## 22.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 8599b89: remove global prisma client as it is not required
8
+
9
+ ## 22.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 4a2f20a: Allow custom session `get`, `start` and `end`
14
+
15
+ ### Patch Changes
16
+
17
+ - 4a2f20a: Set prisma and query on global in dev to prevent instantiating extra `PrismaClient` instances
18
+
19
+ ## 22.1.0
20
+
21
+ ### Minor Changes
22
+
23
+ - b89f4e7: Invalidate user when deleted from database
24
+
25
+ ### Patch Changes
26
+
27
+ - b89f4e7: signin pages error fix
28
+
3
29
  ## 22.0.0
4
30
 
5
31
  ### Major Changes
@@ -2,30 +2,29 @@ import { CookiesOptions, EventCallbacks, PagesOptions } from 'next-auth';
2
2
  import type { KeystoneListsAPI } from '@keystone-6/core/types';
3
3
  import { Provider } from 'next-auth/providers';
4
4
  import { JWTOptions } from 'next-auth/jwt';
5
- declare type CoreNextAuthPageProps = {
5
+ export declare type NextAuthTemplateProps = {
6
6
  autoCreate: boolean;
7
+ identityField: string;
8
+ listKey: string;
9
+ sessionData: string | undefined;
10
+ sessionSecret: string;
11
+ };
12
+ export declare type CoreNextAuthPageProps = {
7
13
  cookies?: Partial<CookiesOptions>;
8
14
  events?: Partial<EventCallbacks>;
9
- identityField: string;
10
15
  jwt?: Partial<JWTOptions>;
11
- listKey: string;
12
16
  pages?: Partial<PagesOptions>;
13
- providers?: Provider[];
17
+ providers: Provider[];
14
18
  resolver?: (args: {
15
19
  user: any;
16
20
  profile: any;
17
21
  account: any;
18
- }) => {
22
+ }) => Promise<{
19
23
  [key: string]: boolean | string | number;
20
- };
21
- sessionData: string | undefined;
22
- sessionSecret: string;
23
- };
24
- declare type NextAuthGglProps = {
25
- mutationName?: string;
26
- query?: KeystoneListsAPI<any>;
24
+ }>;
25
+ } & NextAuthTemplateProps;
26
+ export declare type NextAuthPageProps = CoreNextAuthPageProps & {
27
+ query: KeystoneListsAPI<any>;
27
28
  };
28
- export declare type NextAuthPageProps = CoreNextAuthPageProps & NextAuthGglProps;
29
29
  export default function NextAuthPage(props: NextAuthPageProps): any;
30
30
  export declare const getNextAuthPage: (props: NextAuthPageProps) => () => any;
31
- export {};
@@ -1,4 +1,2 @@
1
- import { NextAuthPageProps } from '../pages/NextAuthPage';
2
- declare type AuthTemplateOptions = NextAuthPageProps;
3
- export declare const authTemplate: ({ autoCreate, identityField, listKey, sessionData, sessionSecret, }: AuthTemplateOptions) => string;
4
- export {};
1
+ import { NextAuthTemplateProps } from '../pages/NextAuthPage';
2
+ export declare const authTemplate: ({ autoCreate, identityField, listKey, sessionData, sessionSecret, }: NextAuthTemplateProps) => string;
@@ -21,11 +21,6 @@ export declare type AuthSessionStrategy<StoredSessionData> = {
21
21
  createContext: CreateContext;
22
22
  }) => Promise<StoredSessionData | undefined>;
23
23
  };
24
- export declare type NextAuthSession = {
25
- listKey: string;
26
- itemId: string;
27
- data: any;
28
- };
29
24
  export declare type NextAuthProviders = Provider[];
30
25
  declare type KeytoneOAuthOptions = {
31
26
  providers: NextAuthProviders;
@@ -164,8 +164,13 @@ const getSchemaExtension = ({
164
164
 
165
165
  const template = `
166
166
  import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
167
- import { query } from '.keystone/api';
168
167
  import keystoneConfig from '../../../../../keystone';
168
+ import { PrismaClient } from '.prisma/client';
169
+ import { createQueryAPI } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/node-api';
170
+
171
+ const keystoneQueryAPI = global.keystoneQueryAPI || createQueryAPI(keystoneConfig, PrismaClient);
172
+
173
+ if (process.env.NODE_ENV !== 'production') globalThis.keystoneQueryAPI = keystoneQueryAPI
169
174
 
170
175
  export default getNextAuthPage({
171
176
  autoCreate: <%= autoCreate %>,
@@ -173,7 +178,7 @@ export default getNextAuthPage({
173
178
  listKey: '<%= listKey %>',
174
179
  pages: keystoneConfig.pages,
175
180
  providers: keystoneConfig.providers,
176
- query,
181
+ query: keystoneQueryAPI,
177
182
  resolver: keystoneConfig.resolver,
178
183
  sessionData: '<%= sessionData %>',
179
184
  sessionSecret: '<%= sessionSecret %>',
@@ -196,7 +201,7 @@ const authTemplate = ({
196
201
  return authOut;
197
202
  };
198
203
 
199
- const _excluded = ["get"];
204
+ const _excluded = ["get", "end"];
200
205
  /**
201
206
  * createAuth function
202
207
  *
@@ -242,7 +247,7 @@ function createAuth({
242
247
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
243
248
 
244
249
  if (isValidSession) {
245
- if (pathname === `${customPath}/api/auth/signin`) {
250
+ if (pathname === `${customPath}/api/auth/signin` || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn)) {
246
251
  return {
247
252
  kind: 'redirect',
248
253
  to: `${customPath}`
@@ -368,48 +373,64 @@ function createAuth({
368
373
 
369
374
 
370
375
  const withItemData = _sessionStrategy => {
371
- const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
376
+ const {
377
+ get,
378
+ end
379
+ } = _sessionStrategy,
380
+ sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
372
381
 
373
382
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
374
- start: async () => {
375
- return 'false';
376
- },
377
383
  get: async ({
378
- req
384
+ req,
385
+ createContext
379
386
  }) => {
380
387
  var _req$headers, _req$headers$authoriz;
381
388
 
389
+ const session = await get({
390
+ req,
391
+ createContext
392
+ });
393
+ const sudoContext = createContext({
394
+ sudo: true
395
+ });
382
396
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
397
+ let nextSession;
383
398
 
384
399
  if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
385
400
  return;
386
401
  }
387
402
 
388
403
  if (((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : (_req$headers$authoriz = _req$headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
389
- var _token$data;
390
-
391
- const token = await jwt.getToken({
404
+ nextSession = await jwt.getToken({
392
405
  req,
393
406
  secret: sessionSecret
394
407
  });
395
-
396
- if (token !== null && token !== void 0 && (_token$data = token.data) !== null && _token$data !== void 0 && _token$data.id) {
397
- return token;
398
- }
408
+ } else {
409
+ nextSession = await react.getSession({
410
+ req
411
+ });
399
412
  }
400
413
 
401
- const nextSession = await react.getSession({
402
- req
403
- });
404
-
405
- if (nextSession) {
406
- return nextSession;
414
+ if (!nextSession || !nextSession.listKey || nextSession.listKey !== listKey || !nextSession.itemId || !sudoContext.query[listKey] || !nextSession.itemId) {
415
+ return;
407
416
  }
417
+
418
+ return _objectSpread(_objectSpread({}, nextSession), {}, {
419
+ data: nextSession.data,
420
+ listKey: nextSession.listKey,
421
+ itemId: nextSession.itemId
422
+ }, session);
408
423
  },
409
424
  end: async ({
410
425
  res,
411
- req
426
+ req,
427
+ createContext
412
428
  }) => {
429
+ await end({
430
+ res,
431
+ req,
432
+ createContext
433
+ });
413
434
  const TOKEN_NAME = process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token';
414
435
  res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
415
436
  maxAge: 0,
@@ -163,8 +163,13 @@ const getSchemaExtension = ({
163
163
 
164
164
  const template = `
165
165
  import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
166
- import { query } from '.keystone/api';
167
166
  import keystoneConfig from '../../../../../keystone';
167
+ import { PrismaClient } from '.prisma/client';
168
+ import { createQueryAPI } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/node-api';
169
+
170
+ const keystoneQueryAPI = global.keystoneQueryAPI || createQueryAPI(keystoneConfig, PrismaClient);
171
+
172
+ if (process.env.NODE_ENV !== 'production') globalThis.keystoneQueryAPI = keystoneQueryAPI
168
173
 
169
174
  export default getNextAuthPage({
170
175
  autoCreate: <%= autoCreate %>,
@@ -172,7 +177,7 @@ export default getNextAuthPage({
172
177
  listKey: '<%= listKey %>',
173
178
  pages: keystoneConfig.pages,
174
179
  providers: keystoneConfig.providers,
175
- query,
180
+ query: keystoneQueryAPI,
176
181
  resolver: keystoneConfig.resolver,
177
182
  sessionData: '<%= sessionData %>',
178
183
  sessionSecret: '<%= sessionSecret %>',
@@ -195,7 +200,7 @@ const authTemplate = ({
195
200
  return authOut;
196
201
  };
197
202
 
198
- const _excluded = ["get"];
203
+ const _excluded = ["get", "end"];
199
204
  /**
200
205
  * createAuth function
201
206
  *
@@ -241,7 +246,7 @@ function createAuth({
241
246
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
242
247
 
243
248
  if (isValidSession) {
244
- if (pathname === `${customPath}/api/auth/signin`) {
249
+ if (pathname === `${customPath}/api/auth/signin` || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn)) {
245
250
  return {
246
251
  kind: 'redirect',
247
252
  to: `${customPath}`
@@ -367,48 +372,64 @@ function createAuth({
367
372
 
368
373
 
369
374
  const withItemData = _sessionStrategy => {
370
- const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
375
+ const {
376
+ get,
377
+ end
378
+ } = _sessionStrategy,
379
+ sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
371
380
 
372
381
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
373
- start: async () => {
374
- return 'false';
375
- },
376
382
  get: async ({
377
- req
383
+ req,
384
+ createContext
378
385
  }) => {
379
386
  var _req$headers, _req$headers$authoriz;
380
387
 
388
+ const session = await get({
389
+ req,
390
+ createContext
391
+ });
392
+ const sudoContext = createContext({
393
+ sudo: true
394
+ });
381
395
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
396
+ let nextSession;
382
397
 
383
398
  if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
384
399
  return;
385
400
  }
386
401
 
387
402
  if (((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : (_req$headers$authoriz = _req$headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
388
- var _token$data;
389
-
390
- const token = await jwt.getToken({
403
+ nextSession = await jwt.getToken({
391
404
  req,
392
405
  secret: sessionSecret
393
406
  });
394
-
395
- if (token !== null && token !== void 0 && (_token$data = token.data) !== null && _token$data !== void 0 && _token$data.id) {
396
- return token;
397
- }
407
+ } else {
408
+ nextSession = await react.getSession({
409
+ req
410
+ });
398
411
  }
399
412
 
400
- const nextSession = await react.getSession({
401
- req
402
- });
403
-
404
- if (nextSession) {
405
- return nextSession;
413
+ if (!nextSession || !nextSession.listKey || nextSession.listKey !== listKey || !nextSession.itemId || !sudoContext.query[listKey] || !nextSession.itemId) {
414
+ return;
406
415
  }
416
+
417
+ return _objectSpread(_objectSpread({}, nextSession), {}, {
418
+ data: nextSession.data,
419
+ listKey: nextSession.listKey,
420
+ itemId: nextSession.itemId
421
+ }, session);
407
422
  },
408
423
  end: async ({
409
424
  res,
410
- req
425
+ req,
426
+ createContext
411
427
  }) => {
428
+ await end({
429
+ res,
430
+ req,
431
+ createContext
432
+ });
412
433
  const TOKEN_NAME = '__Secure-next-auth.session-token' ;
413
434
  res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
414
435
  maxAge: 0,
@@ -131,8 +131,13 @@ const getSchemaExtension = ({
131
131
 
132
132
  const template = `
133
133
  import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
134
- import { query } from '.keystone/api';
135
134
  import keystoneConfig from '../../../../../keystone';
135
+ import { PrismaClient } from '.prisma/client';
136
+ import { createQueryAPI } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/node-api';
137
+
138
+ const keystoneQueryAPI = global.keystoneQueryAPI || createQueryAPI(keystoneConfig, PrismaClient);
139
+
140
+ if (process.env.NODE_ENV !== 'production') globalThis.keystoneQueryAPI = keystoneQueryAPI
136
141
 
137
142
  export default getNextAuthPage({
138
143
  autoCreate: <%= autoCreate %>,
@@ -140,7 +145,7 @@ export default getNextAuthPage({
140
145
  listKey: '<%= listKey %>',
141
146
  pages: keystoneConfig.pages,
142
147
  providers: keystoneConfig.providers,
143
- query,
148
+ query: keystoneQueryAPI,
144
149
  resolver: keystoneConfig.resolver,
145
150
  sessionData: '<%= sessionData %>',
146
151
  sessionSecret: '<%= sessionSecret %>',
@@ -163,7 +168,7 @@ const authTemplate = ({
163
168
  return authOut;
164
169
  };
165
170
 
166
- const _excluded = ["get"];
171
+ const _excluded = ["get", "end"];
167
172
  /**
168
173
  * createAuth function
169
174
  *
@@ -209,7 +214,7 @@ function createAuth({
209
214
  const pathname = url.parse(req === null || req === void 0 ? void 0 : req.url).pathname;
210
215
 
211
216
  if (isValidSession) {
212
- if (pathname === `${customPath}/api/auth/signin`) {
217
+ if (pathname === `${customPath}/api/auth/signin` || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty(pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn)) {
213
218
  return {
214
219
  kind: 'redirect',
215
220
  to: `${customPath}`
@@ -335,48 +340,64 @@ function createAuth({
335
340
 
336
341
 
337
342
  const withItemData = _sessionStrategy => {
338
- const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
343
+ const {
344
+ get,
345
+ end
346
+ } = _sessionStrategy,
347
+ sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
339
348
 
340
349
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
341
- start: async () => {
342
- return 'false';
343
- },
344
350
  get: async ({
345
- req
351
+ req,
352
+ createContext
346
353
  }) => {
347
354
  var _req$headers, _req$headers$authoriz;
348
355
 
356
+ const session = await get({
357
+ req,
358
+ createContext
359
+ });
360
+ const sudoContext = createContext({
361
+ sudo: true
362
+ });
349
363
  const pathname = url.parse(req === null || req === void 0 ? void 0 : req.url).pathname;
364
+ let nextSession;
350
365
 
351
366
  if (_includesInstanceProperty(pathname).call(pathname, '/api/auth')) {
352
367
  return;
353
368
  }
354
369
 
355
370
  if (((_req$headers = req.headers) === null || _req$headers === void 0 ? void 0 : (_req$headers$authoriz = _req$headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
356
- var _token$data;
357
-
358
- const token = await getToken({
371
+ nextSession = await getToken({
359
372
  req,
360
373
  secret: sessionSecret
361
374
  });
362
-
363
- if (token !== null && token !== void 0 && (_token$data = token.data) !== null && _token$data !== void 0 && _token$data.id) {
364
- return token;
365
- }
375
+ } else {
376
+ nextSession = await getSession({
377
+ req
378
+ });
366
379
  }
367
380
 
368
- const nextSession = await getSession({
369
- req
370
- });
371
-
372
- if (nextSession) {
373
- return nextSession;
381
+ if (!nextSession || !nextSession.listKey || nextSession.listKey !== listKey || !nextSession.itemId || !sudoContext.query[listKey] || !nextSession.itemId) {
382
+ return;
374
383
  }
384
+
385
+ return _objectSpread(_objectSpread({}, nextSession), {}, {
386
+ data: nextSession.data,
387
+ listKey: nextSession.listKey,
388
+ itemId: nextSession.itemId
389
+ }, session);
375
390
  },
376
391
  end: async ({
377
392
  res,
378
- req
393
+ req,
394
+ createContext
379
395
  }) => {
396
+ await end({
397
+ res,
398
+ req,
399
+ createContext
400
+ });
380
401
  const TOKEN_NAME = process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token';
381
402
  res.setHeader('Set-Cookie', cookie.serialize(TOKEN_NAME, '', {
382
403
  maxAge: 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensaas/keystone-nextjs-auth",
3
- "version": "22.0.0",
3
+ "version": "22.2.1",
4
4
  "repository": "https://github.com/opensaasau/keystone-nextjs-auth",
5
5
  "license": "MIT",
6
6
  "main": "dist/opensaas-keystone-nextjs-auth.cjs.js",
@@ -17,16 +17,14 @@
17
17
  },
18
18
  "devDependencies": {
19
19
  "@keystone-6/core": "^1.1.0",
20
- "next": "12.1.0",
21
20
  "react": "^17.0.2"
22
21
  },
23
22
  "peerDependencies": {
24
23
  "@keystone-6/core": "^1.1.0",
25
- "next": "12.1.0",
26
24
  "react": "^17.0.2"
27
25
  },
28
26
  "engines": {
29
- "node": "^12.20 || >= 14.13"
27
+ "node": "^14.13 || >= 16.13"
30
28
  },
31
29
  "publishConfig": {
32
30
  "access": "public"
@@ -81,7 +81,6 @@ function NextAuthPage(props) {
81
81
  }
82
82
 
83
83
  const list = query[listKey];
84
- const queryAPI = query[listKey];
85
84
  const protectIdentities = true;
86
85
  return NextAuth__default["default"]({
87
86
  cookies,
@@ -111,7 +110,7 @@ function NextAuthPage(props) {
111
110
  account,
112
111
  profile
113
112
  }) : {};
114
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI); // ID
113
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list); // ID
115
114
 
116
115
  const data = _objectSpread({
117
116
  [identityField]: identity
@@ -119,11 +118,9 @@ function NextAuthPage(props) {
119
118
 
120
119
  if (!result.success) {
121
120
  if (!autoCreate) {
122
- console.log('`autoCreate` is set to `false`, skipping user auto-creation');
123
121
  return false;
124
122
  }
125
123
 
126
- console.log('`autoCreate` is set to `true`, auto-creating a new user');
127
124
  const createUser = await list.createOne({
128
125
  data
129
126
  }).then(returned => {
@@ -132,14 +129,12 @@ function NextAuthPage(props) {
132
129
  user: returned
133
130
  };
134
131
  }).catch(error => {
135
- console.log(error);
132
+ console.error(error);
136
133
  throw new Error(error);
137
134
  });
138
- console.log('Created User', createUser);
139
135
  return createUser.success;
140
136
  }
141
137
 
142
- console.log('Data', data);
143
138
  const updateUser = await list.updateOne({
144
139
  where: {
145
140
  id: result.item.id
@@ -151,7 +146,7 @@ function NextAuthPage(props) {
151
146
  user: returned
152
147
  };
153
148
  }).catch(error => {
154
- console.log(error);
149
+ console.error(error);
155
150
  throw new Error(error);
156
151
  });
157
152
  return updateUser.success;
@@ -167,12 +162,20 @@ function NextAuthPage(props) {
167
162
  session,
168
163
  token
169
164
  }) {
170
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
171
- data: token.data,
172
- subject: token.sub,
173
- listKey: token.listKey,
174
- itemId: token.itemId
175
- });
165
+ let returnSession = session;
166
+
167
+ if (!token.itemId) {
168
+ return {
169
+ expires: '0'
170
+ };
171
+ } else {
172
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
173
+ data: token.data,
174
+ subject: token.sub,
175
+ listKey: token.listKey,
176
+ itemId: token.itemId
177
+ });
178
+ }
176
179
 
177
180
  return returnSession;
178
181
  },
@@ -181,26 +184,22 @@ function NextAuthPage(props) {
181
184
  token
182
185
  }) {
183
186
  const identity = token.sub;
187
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list);
184
188
 
185
- if (!token.itemId) {
186
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
187
-
188
- if (!result.success) {
189
- return token;
190
- }
191
-
189
+ if (!result.success) {
190
+ token.itemId = null;
191
+ } else {
192
192
  token.itemId = result.item.id;
193
+ const data = await query[listKey].findOne({
194
+ where: {
195
+ id: token.itemId
196
+ },
197
+ query: sessionData || 'id'
198
+ });
199
+ token.data = data;
193
200
  }
194
201
 
195
- const data = await query[listKey].findOne({
196
- where: {
197
- id: token.itemId
198
- },
199
- query: sessionData || 'id'
200
- });
201
-
202
202
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
203
- data,
204
203
  subject: token.sub,
205
204
  listKey
206
205
  });
@@ -81,7 +81,6 @@ function NextAuthPage(props) {
81
81
  }
82
82
 
83
83
  const list = query[listKey];
84
- const queryAPI = query[listKey];
85
84
  const protectIdentities = true;
86
85
  return NextAuth__default["default"]({
87
86
  cookies,
@@ -111,7 +110,7 @@ function NextAuthPage(props) {
111
110
  account,
112
111
  profile
113
112
  }) : {};
114
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI); // ID
113
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list); // ID
115
114
 
116
115
  const data = _objectSpread({
117
116
  [identityField]: identity
@@ -119,11 +118,9 @@ function NextAuthPage(props) {
119
118
 
120
119
  if (!result.success) {
121
120
  if (!autoCreate) {
122
- console.log('`autoCreate` is set to `false`, skipping user auto-creation');
123
121
  return false;
124
122
  }
125
123
 
126
- console.log('`autoCreate` is set to `true`, auto-creating a new user');
127
124
  const createUser = await list.createOne({
128
125
  data
129
126
  }).then(returned => {
@@ -132,14 +129,12 @@ function NextAuthPage(props) {
132
129
  user: returned
133
130
  };
134
131
  }).catch(error => {
135
- console.log(error);
132
+ console.error(error);
136
133
  throw new Error(error);
137
134
  });
138
- console.log('Created User', createUser);
139
135
  return createUser.success;
140
136
  }
141
137
 
142
- console.log('Data', data);
143
138
  const updateUser = await list.updateOne({
144
139
  where: {
145
140
  id: result.item.id
@@ -151,7 +146,7 @@ function NextAuthPage(props) {
151
146
  user: returned
152
147
  };
153
148
  }).catch(error => {
154
- console.log(error);
149
+ console.error(error);
155
150
  throw new Error(error);
156
151
  });
157
152
  return updateUser.success;
@@ -167,12 +162,20 @@ function NextAuthPage(props) {
167
162
  session,
168
163
  token
169
164
  }) {
170
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
171
- data: token.data,
172
- subject: token.sub,
173
- listKey: token.listKey,
174
- itemId: token.itemId
175
- });
165
+ let returnSession = session;
166
+
167
+ if (!token.itemId) {
168
+ return {
169
+ expires: '0'
170
+ };
171
+ } else {
172
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
173
+ data: token.data,
174
+ subject: token.sub,
175
+ listKey: token.listKey,
176
+ itemId: token.itemId
177
+ });
178
+ }
176
179
 
177
180
  return returnSession;
178
181
  },
@@ -181,26 +184,22 @@ function NextAuthPage(props) {
181
184
  token
182
185
  }) {
183
186
  const identity = token.sub;
187
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list);
184
188
 
185
- if (!token.itemId) {
186
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
187
-
188
- if (!result.success) {
189
- return token;
190
- }
191
-
189
+ if (!result.success) {
190
+ token.itemId = null;
191
+ } else {
192
192
  token.itemId = result.item.id;
193
+ const data = await query[listKey].findOne({
194
+ where: {
195
+ id: token.itemId
196
+ },
197
+ query: sessionData || 'id'
198
+ });
199
+ token.data = data;
193
200
  }
194
201
 
195
- const data = await query[listKey].findOne({
196
- where: {
197
- id: token.itemId
198
- },
199
- query: sessionData || 'id'
200
- });
201
-
202
202
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
203
- data,
204
203
  subject: token.sub,
205
204
  listKey
206
205
  });
@@ -73,7 +73,6 @@ function NextAuthPage(props) {
73
73
  }
74
74
 
75
75
  const list = query[listKey];
76
- const queryAPI = query[listKey];
77
76
  const protectIdentities = true;
78
77
  return NextAuth({
79
78
  cookies,
@@ -103,7 +102,7 @@ function NextAuthPage(props) {
103
102
  account,
104
103
  profile
105
104
  }) : {};
106
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI); // ID
105
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list); // ID
107
106
 
108
107
  const data = _objectSpread({
109
108
  [identityField]: identity
@@ -111,11 +110,9 @@ function NextAuthPage(props) {
111
110
 
112
111
  if (!result.success) {
113
112
  if (!autoCreate) {
114
- console.log('`autoCreate` is set to `false`, skipping user auto-creation');
115
113
  return false;
116
114
  }
117
115
 
118
- console.log('`autoCreate` is set to `true`, auto-creating a new user');
119
116
  const createUser = await list.createOne({
120
117
  data
121
118
  }).then(returned => {
@@ -124,14 +121,12 @@ function NextAuthPage(props) {
124
121
  user: returned
125
122
  };
126
123
  }).catch(error => {
127
- console.log(error);
124
+ console.error(error);
128
125
  throw new Error(error);
129
126
  });
130
- console.log('Created User', createUser);
131
127
  return createUser.success;
132
128
  }
133
129
 
134
- console.log('Data', data);
135
130
  const updateUser = await list.updateOne({
136
131
  where: {
137
132
  id: result.item.id
@@ -143,7 +138,7 @@ function NextAuthPage(props) {
143
138
  user: returned
144
139
  };
145
140
  }).catch(error => {
146
- console.log(error);
141
+ console.error(error);
147
142
  throw new Error(error);
148
143
  });
149
144
  return updateUser.success;
@@ -159,12 +154,20 @@ function NextAuthPage(props) {
159
154
  session,
160
155
  token
161
156
  }) {
162
- const returnSession = _objectSpread(_objectSpread({}, session), {}, {
163
- data: token.data,
164
- subject: token.sub,
165
- listKey: token.listKey,
166
- itemId: token.itemId
167
- });
157
+ let returnSession = session;
158
+
159
+ if (!token.itemId) {
160
+ return {
161
+ expires: '0'
162
+ };
163
+ } else {
164
+ returnSession = _objectSpread(_objectSpread({}, session), {}, {
165
+ data: token.data,
166
+ subject: token.sub,
167
+ listKey: token.listKey,
168
+ itemId: token.itemId
169
+ });
170
+ }
168
171
 
169
172
  return returnSession;
170
173
  },
@@ -173,26 +176,22 @@ function NextAuthPage(props) {
173
176
  token
174
177
  }) {
175
178
  const identity = token.sub;
179
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list);
176
180
 
177
- if (!token.itemId) {
178
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
179
-
180
- if (!result.success) {
181
- return token;
182
- }
183
-
181
+ if (!result.success) {
182
+ token.itemId = null;
183
+ } else {
184
184
  token.itemId = result.item.id;
185
+ const data = await query[listKey].findOne({
186
+ where: {
187
+ id: token.itemId
188
+ },
189
+ query: sessionData || 'id'
190
+ });
191
+ token.data = data;
185
192
  }
186
193
 
187
- const data = await query[listKey].findOne({
188
- where: {
189
- id: token.itemId
190
- },
191
- query: sessionData || 'id'
192
- });
193
-
194
194
  const returnToken = _objectSpread(_objectSpread({}, token), {}, {
195
- data,
196
195
  subject: token.sub,
197
196
  listKey
198
197
  });
package/src/index.ts CHANGED
@@ -14,10 +14,11 @@ import { Provider } from 'next-auth/providers';
14
14
 
15
15
  import * as cookie from 'cookie';
16
16
 
17
+ import { Session } from 'next-auth';
17
18
  import { nextConfigTemplate } from './templates/next-config';
18
19
  // import * as Path from 'path';
19
20
 
20
- import { AuthConfig, KeystoneOAuthConfig, NextAuthSession, AuthSessionStrategy } from './types';
21
+ import { AuthConfig, KeystoneOAuthConfig, AuthSessionStrategy } from './types';
21
22
  import { getSchemaExtension } from './schema';
22
23
  import { authTemplate } from './templates/auth';
23
24
 
@@ -64,7 +65,10 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
64
65
  const pathname = url.parse(req?.url!).pathname!;
65
66
 
66
67
  if (isValidSession) {
67
- if (pathname === `${customPath}/api/auth/signin`) {
68
+ if (
69
+ pathname === `${customPath}/api/auth/signin` ||
70
+ (pages?.signIn && pathname.includes(pages?.signIn))
71
+ ) {
68
72
  return { kind: 'redirect', to: `${customPath}` };
69
73
  }
70
74
  if (customPath !== '' && pathname === '/') {
@@ -189,35 +193,47 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
189
193
  */
190
194
  const withItemData = (
191
195
  _sessionStrategy: AuthSessionStrategy<Record<string, any>>
192
- ): AuthSessionStrategy<NextAuthSession | never> => {
193
- const { get, ...sessionStrategy } = _sessionStrategy;
196
+ ): AuthSessionStrategy<{ listKey: string; itemId: string; data: any }> => {
197
+ const { get, end, ...sessionStrategy } = _sessionStrategy;
194
198
  return {
195
199
  ...sessionStrategy,
196
- start: async () => {
197
- return 'false';
198
- },
199
- get: async ({ req }) => {
200
+ get: async ({ req, createContext }) => {
201
+ const session = await get({ req, createContext });
202
+ const sudoContext = createContext({ sudo: true });
200
203
  const pathname = url.parse(req?.url!).pathname!;
204
+ let nextSession: Session;
201
205
  if (pathname.includes('/api/auth')) {
202
206
  return;
203
207
  }
204
208
  if (req.headers?.authorization?.split(' ')[0] === 'Bearer') {
205
- const token = (await getToken({
209
+ nextSession = (await getToken({
206
210
  req,
207
211
  secret: sessionSecret,
208
- })) as NextAuthSession;
209
-
210
- if (token?.data?.id) {
211
- return token;
212
- }
212
+ })) as Session;
213
+ } else {
214
+ nextSession = (await getSession({ req })) as Session;
213
215
  }
214
- const nextSession: unknown = await getSession({ req });
215
216
 
216
- if (nextSession) {
217
- return nextSession as NextAuthSession;
217
+ if (
218
+ !nextSession ||
219
+ !nextSession.listKey ||
220
+ nextSession.listKey !== listKey ||
221
+ !nextSession.itemId ||
222
+ !sudoContext.query[listKey] ||
223
+ !nextSession.itemId
224
+ ) {
225
+ return;
218
226
  }
227
+ return {
228
+ ...nextSession,
229
+ data: nextSession.data,
230
+ listKey: nextSession.listKey,
231
+ itemId: nextSession.itemId,
232
+ ...session,
233
+ };
219
234
  },
220
- end: async ({ res, req }) => {
235
+ end: async ({ res, req, createContext }) => {
236
+ await end({ res, req, createContext });
221
237
  const TOKEN_NAME =
222
238
  process.env.NODE_ENV === 'production'
223
239
  ? '__Secure-next-auth.session-token'
@@ -4,28 +4,28 @@ import { Provider } from 'next-auth/providers';
4
4
  import { JWTOptions } from 'next-auth/jwt';
5
5
  import { validateNextAuth } from '../lib/validateNextAuth';
6
6
 
7
- type CoreNextAuthPageProps = {
7
+ export type NextAuthTemplateProps = {
8
8
  autoCreate: boolean;
9
- cookies?: Partial<CookiesOptions>;
10
- events?: Partial<EventCallbacks>;
11
9
  identityField: string;
12
- jwt?: Partial<JWTOptions>;
13
10
  listKey: string;
14
- pages?: Partial<PagesOptions>;
15
- providers?: Provider[];
16
- resolver?: (args: { user: any; profile: any; account: any }) => {
17
- [key: string]: boolean | string | number;
18
- };
19
11
  sessionData: string | undefined;
20
12
  sessionSecret: string;
21
13
  };
22
14
 
23
- type NextAuthGglProps = {
24
- mutationName?: string;
25
- query?: KeystoneListsAPI<any>;
26
- };
15
+ export type CoreNextAuthPageProps = {
16
+ cookies?: Partial<CookiesOptions>;
17
+ events?: Partial<EventCallbacks>;
18
+ jwt?: Partial<JWTOptions>;
19
+ pages?: Partial<PagesOptions>;
20
+ providers: Provider[];
21
+ resolver?: (args: { user: any; profile: any; account: any }) => Promise<{
22
+ [key: string]: boolean | string | number;
23
+ }>;
24
+ } & NextAuthTemplateProps;
27
25
 
28
- export type NextAuthPageProps = CoreNextAuthPageProps & NextAuthGglProps;
26
+ export type NextAuthPageProps = CoreNextAuthPageProps & {
27
+ query: KeystoneListsAPI<any>;
28
+ };
29
29
 
30
30
  export default function NextAuthPage(props: NextAuthPageProps) {
31
31
  const {
@@ -54,7 +54,6 @@ export default function NextAuthPage(props: NextAuthPageProps) {
54
54
  }
55
55
 
56
56
  const list = query[listKey];
57
- const queryAPI = query[listKey];
58
57
  const protectIdentities = true;
59
58
 
60
59
  return NextAuth({
@@ -76,7 +75,7 @@ export default function NextAuthPage(props: NextAuthPageProps) {
76
75
  }
77
76
  const userInput = resolver ? await resolver({ user, account, profile }) : {};
78
77
 
79
- const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
78
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list);
80
79
  // ID
81
80
  const data: any = {
82
81
  [identityField]: identity,
@@ -85,10 +84,8 @@ export default function NextAuthPage(props: NextAuthPageProps) {
85
84
 
86
85
  if (!result.success) {
87
86
  if (!autoCreate) {
88
- console.log('`autoCreate` is set to `false`, skipping user auto-creation');
89
87
  return false;
90
88
  }
91
- console.log('`autoCreate` is set to `true`, auto-creating a new user');
92
89
 
93
90
  const createUser = await list
94
91
  .createOne({ data })
@@ -96,13 +93,11 @@ export default function NextAuthPage(props: NextAuthPageProps) {
96
93
  return { success: true, user: returned };
97
94
  })
98
95
  .catch(error => {
99
- console.log(error);
96
+ console.error(error);
100
97
  throw new Error(error);
101
98
  });
102
- console.log('Created User', createUser);
103
99
  return createUser.success;
104
100
  }
105
- console.log('Data', data);
106
101
 
107
102
  const updateUser = await list
108
103
  .updateOne({ where: { id: result.item.id }, data })
@@ -110,7 +105,7 @@ export default function NextAuthPage(props: NextAuthPageProps) {
110
105
  return { success: true, user: returned };
111
106
  })
112
107
  .catch(error => {
113
- console.log(error);
108
+ console.error(error);
114
109
  throw new Error(error);
115
110
  });
116
111
  return updateUser.success;
@@ -119,37 +114,37 @@ export default function NextAuthPage(props: NextAuthPageProps) {
119
114
  return url;
120
115
  },
121
116
  async session({ session, token }) {
122
- const returnSession = {
123
- ...session,
124
- data: token.data,
125
- subject: token.sub,
126
- listKey: token.listKey,
127
- itemId: token.itemId,
128
- };
117
+ let returnSession = session;
118
+ if (!token.itemId) {
119
+ return { expires: '0' };
120
+ } else {
121
+ returnSession = {
122
+ ...session,
123
+ data: token.data,
124
+ subject: token.sub,
125
+ listKey: token.listKey as string,
126
+ itemId: token.itemId as string,
127
+ };
128
+ }
129
+
129
130
  return returnSession;
130
131
  },
131
132
  async jwt({ token }) {
132
133
  const identity = token.sub as number | string;
133
- if (!token.itemId) {
134
- const result = await validateNextAuth(
135
- identityField,
136
- identity,
137
- protectIdentities,
138
- queryAPI
139
- );
140
-
141
- if (!result.success) {
142
- return token;
143
- }
134
+ const result = await validateNextAuth(identityField, identity, protectIdentities, list);
135
+
136
+ if (!result.success) {
137
+ token.itemId = null;
138
+ } else {
144
139
  token.itemId = result.item.id;
140
+ const data = await query[listKey].findOne({
141
+ where: { id: token.itemId },
142
+ query: sessionData || 'id',
143
+ });
144
+ token.data = data;
145
145
  }
146
- const data = await query[listKey].findOne({
147
- where: { id: token.itemId },
148
- query: sessionData || 'id',
149
- });
150
146
  const returnToken = {
151
147
  ...token,
152
- data,
153
148
  subject: token.sub,
154
149
  listKey,
155
150
  };
@@ -1,10 +1,15 @@
1
1
  import ejs from 'ejs';
2
- import { NextAuthPageProps } from '../pages/NextAuthPage';
2
+ import { NextAuthTemplateProps } from '../pages/NextAuthPage';
3
3
 
4
4
  const template = `
5
5
  import getNextAuthPage from '@opensaas/keystone-nextjs-auth/pages/NextAuthPage';
6
- import { query } from '.keystone/api';
7
6
  import keystoneConfig from '../../../../../keystone';
7
+ import { PrismaClient } from '.prisma/client';
8
+ import { createQueryAPI } from '@keystone-6/core/___internal-do-not-use-will-break-in-patch/node-api';
9
+
10
+ const keystoneQueryAPI = global.keystoneQueryAPI || createQueryAPI(keystoneConfig, PrismaClient);
11
+
12
+ if (process.env.NODE_ENV !== 'production') globalThis.keystoneQueryAPI = keystoneQueryAPI
8
13
 
9
14
  export default getNextAuthPage({
10
15
  autoCreate: <%= autoCreate %>,
@@ -12,22 +17,20 @@ export default getNextAuthPage({
12
17
  listKey: '<%= listKey %>',
13
18
  pages: keystoneConfig.pages,
14
19
  providers: keystoneConfig.providers,
15
- query,
20
+ query: keystoneQueryAPI,
16
21
  resolver: keystoneConfig.resolver,
17
22
  sessionData: '<%= sessionData %>',
18
23
  sessionSecret: '<%= sessionSecret %>',
19
24
  });
20
25
  `;
21
26
 
22
- type AuthTemplateOptions = NextAuthPageProps;
23
-
24
27
  export const authTemplate = ({
25
28
  autoCreate,
26
29
  identityField,
27
30
  listKey,
28
31
  sessionData,
29
32
  sessionSecret,
30
- }: AuthTemplateOptions) => {
33
+ }: NextAuthTemplateProps) => {
31
34
  const authOut = ejs.render(template, {
32
35
  identityField,
33
36
  sessionData,
@@ -23,8 +23,6 @@ export declare type AuthSessionStrategy<StoredSessionData> = {
23
23
  }) => Promise<StoredSessionData | undefined>;
24
24
  };
25
25
 
26
- export type NextAuthSession = { listKey: string; itemId: string; data: any };
27
-
28
26
  export type NextAuthProviders = Provider[];
29
27
 
30
28
  type KeytoneOAuthOptions = {
@@ -0,0 +1,19 @@
1
+ import NextAuth from 'next-auth';
2
+ import { JWT } from 'next-auth/jwt';
3
+
4
+ declare module 'next-auth' {
5
+ interface JWT {
6
+ data?: any | undefined;
7
+ subject?: string | undefined;
8
+ listKey?: string;
9
+ itemId?: string | undefined;
10
+ name?: string | null | undefined;
11
+ email?: string | null | undefined;
12
+ picture?: string | null | undefined;
13
+ sub?: string | null | undefined;
14
+ expires?: string | null | undefined;
15
+ }
16
+ interface Session extends JWT {
17
+ user?: any;
18
+ }
19
+ }