@opensaas/keystone-nextjs-auth 20.5.0 → 21.1.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.
@@ -7,14 +7,13 @@ var _objectWithoutProperties = require('@babel/runtime/helpers/objectWithoutProp
7
7
  var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
8
8
  var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
9
9
  var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
10
- var _URL = require('@babel/runtime-corejs3/core-js-stable/url');
10
+ require('@babel/runtime-corejs3/core-js-stable/url');
11
11
  var url = require('url');
12
12
  var react = require('next-auth/react');
13
13
  var jwt = require('next-auth/jwt');
14
14
  var cookie = require('cookie');
15
15
  var ejs = require('ejs');
16
16
  var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
17
- var graphql = require('graphql');
18
17
  var core = require('@keystone-6/core');
19
18
 
20
19
  function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
@@ -40,7 +39,6 @@ function _interopNamespace(e) {
40
39
  var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
41
40
  var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty);
42
41
  var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
43
- var _URL__default = /*#__PURE__*/_interopDefault(_URL);
44
42
  var url__default = /*#__PURE__*/_interopDefault(url);
45
43
  var cookie__namespace = /*#__PURE__*/_interopNamespace(cookie);
46
44
  var ejs__default = /*#__PURE__*/_interopDefault(ejs);
@@ -55,6 +53,9 @@ module.exports = withPreconstruct({
55
53
  typescript: {
56
54
  ignoreBuildErrors: true,
57
55
  },
56
+ env: {
57
+ NEXTAUTH_URL: process.env.NEXTAUTH_URL || 'http://localhost:<%= process.env.PORT || 3000 %><%= keystonePath || '' %>/api/auth',
58
+ },
58
59
  eslint: {
59
60
  ignoreDuringBuilds: true,
60
61
  },
@@ -110,7 +111,6 @@ const nextConfigTemplate = ({
110
111
 
111
112
  function getBaseAuthSchema({
112
113
  listKey,
113
- gqlNames,
114
114
  base
115
115
  }) {
116
116
  const extension = {
@@ -150,22 +150,12 @@ function getBaseAuthSchema({
150
150
  }
151
151
 
152
152
  const getSchemaExtension = ({
153
- identityField,
154
- listKey,
155
- gqlNames
153
+ listKey
156
154
  }) => core.graphql.extend(base => {
157
155
  var _context;
158
156
 
159
- const uniqueWhereInputType = graphql.assertInputObjectType(base.schema.getType(`${listKey}WhereUniqueInput`));
160
- const identityFieldOnUniqueWhere = uniqueWhereInputType.getFields()[identityField];
161
-
162
- if ((identityFieldOnUniqueWhere === null || identityFieldOnUniqueWhere === void 0 ? void 0 : identityFieldOnUniqueWhere.type) !== graphql.GraphQLString && (identityFieldOnUniqueWhere === null || identityFieldOnUniqueWhere === void 0 ? void 0 : identityFieldOnUniqueWhere.type) !== graphql.GraphQLID) {
163
- throw new Error(`createAuth was called with an identityField of ${identityField} on the list ${listKey} ` + `but that field doesn't allow being searched uniquely with a String or ID. ` + `You should likely add \`isIndexed: 'unique'\` ` + `to the field at ${listKey}.${identityField}`);
164
- }
165
-
166
157
  const baseSchema = getBaseAuthSchema({
167
158
  listKey,
168
- gqlNames,
169
159
  base
170
160
  });
171
161
  return _filterInstanceProperty__default["default"](_context = [baseSchema.extension]).call(_context, x => x !== undefined);
@@ -177,38 +167,29 @@ import { query } from '.keystone/api';
177
167
  import keystoneConfig from '../../../../../keystone';
178
168
 
179
169
  export default getNextAuthPage({
170
+ autoCreate: <%= autoCreate %>,
180
171
  identityField: '<%= identityField %>',
181
- sessionData: '<%= sessionData %>',
182
172
  listKey: '<%= listKey %>',
183
- userMap: <%- JSON.stringify(userMap) %>,
184
- accountMap: <%- JSON.stringify(accountMap) %>,
185
- profileMap: <%- JSON.stringify(profileMap) %>,
186
- autoCreate: <%= autoCreate %>,
187
- sessionSecret: '<%= sessionSecret %>',
173
+ pages: keystoneConfig.pages,
188
174
  providers: keystoneConfig.providers,
189
175
  query,
176
+ resolver: keystoneConfig.resolver,
177
+ sessionData: '<%= sessionData %>',
178
+ sessionSecret: '<%= sessionSecret %>',
190
179
  });
191
180
  `;
192
181
  const authTemplate = ({
193
- gqlNames,
182
+ autoCreate,
194
183
  identityField,
195
- sessionData,
196
184
  listKey,
197
- autoCreate,
198
- userMap,
199
- accountMap,
200
- profileMap,
185
+ sessionData,
201
186
  sessionSecret
202
187
  }) => {
203
188
  const authOut = ejs__default["default"].render(template, {
204
- gqlNames,
205
189
  identityField,
206
190
  sessionData,
207
191
  listKey,
208
192
  autoCreate,
209
- userMap,
210
- accountMap,
211
- profileMap,
212
193
  sessionSecret
213
194
  });
214
195
  return authOut;
@@ -222,32 +203,22 @@ const _excluded = ["get", "start"];
222
203
  */
223
204
 
224
205
  function createAuth({
225
- listKey,
226
- identityField,
227
- sessionData,
228
206
  autoCreate,
229
- userMap,
230
- accountMap,
231
- profileMap,
207
+ cookies,
208
+ identityField,
209
+ listKey,
232
210
  keystonePath,
211
+ pages,
212
+ resolver,
233
213
  providers,
214
+ sessionData,
234
215
  sessionSecret
235
216
  }) {
236
217
  // The protectIdentities flag is currently under review to see whether it should be
237
218
  // part of the createAuth API (in which case its use cases need to be documented and tested)
238
219
  // or whether always being true is what we want, in which case we can refactor our code
239
220
  // to match this. -TL
240
- const gqlNames = {
241
- // Core
242
- authenticateItemWithPassword: `authenticate${listKey}WithPassword`,
243
- ItemAuthenticationWithPasswordResult: `${listKey}AuthenticationWithPasswordResult`,
244
- ItemAuthenticationWithPasswordSuccess: `${listKey}AuthenticationWithPasswordSuccess`,
245
- ItemAuthenticationWithPasswordFailure: `${listKey}AuthenticationWithPasswordFailure`,
246
- // Initial data
247
- CreateInitialInput: `CreateInitial${listKey}Input`,
248
- createInitialItem: `createInitial${listKey}`
249
- };
250
- const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
221
+ const customPath = !keystonePath || keystonePath === "/" ? "" : keystonePath;
251
222
  /**
252
223
  * pageMiddleware
253
224
  *
@@ -269,21 +240,17 @@ function createAuth({
269
240
  } = context;
270
241
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
271
242
 
272
- if (pathname === `${customPath}/api/__keystone_api_build`) {
273
- return;
274
- }
275
-
276
243
  if (isValidSession) {
277
244
  if (pathname === `${customPath}/api/auth/signin`) {
278
245
  return {
279
- kind: 'redirect',
246
+ kind: "redirect",
280
247
  to: `${customPath}`
281
248
  };
282
249
  }
283
250
 
284
- if (customPath !== '' && pathname === '/') {
251
+ if (customPath !== "" && pathname === "/") {
285
252
  return {
286
- kind: 'redirect',
253
+ kind: "redirect",
287
254
  to: `${customPath}`
288
255
  };
289
256
  }
@@ -291,10 +258,14 @@ function createAuth({
291
258
  return;
292
259
  }
293
260
 
261
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/_next/") || _includesInstanceProperty__default["default"](pathname).call(pathname, "/api/auth/") || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
262
+ return;
263
+ }
264
+
294
265
  if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
295
266
  return {
296
- kind: 'redirect',
297
- to: `${customPath}/api/auth/signin`
267
+ kind: "redirect",
268
+ to: (pages === null || pages === void 0 ? void 0 : pages.signIn) || `${customPath}/api/auth/signin`
298
269
  };
299
270
  }
300
271
  };
@@ -310,22 +281,18 @@ function createAuth({
310
281
 
311
282
  const getAdditionalFiles = () => {
312
283
  const filesToWrite = [{
313
- mode: 'write',
314
- outputPath: 'pages/api/auth/[...nextauth].js',
284
+ mode: "write",
285
+ outputPath: "pages/api/auth/[...nextauth].js",
315
286
  src: authTemplate({
316
- gqlNames,
287
+ autoCreate,
317
288
  identityField,
318
- sessionData,
319
289
  listKey,
320
- autoCreate,
321
- userMap,
322
- accountMap,
323
- profileMap,
290
+ sessionData,
324
291
  sessionSecret
325
292
  })
326
293
  }, {
327
- mode: 'write',
328
- outputPath: 'next.config.js',
294
+ mode: "write",
295
+ outputPath: "next.config.js",
329
296
  src: nextConfigTemplate({
330
297
  keystonePath: customPath
331
298
  })
@@ -339,7 +306,8 @@ function createAuth({
339
306
  */
340
307
 
341
308
 
342
- const publicPages = [`${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`];
309
+ const publicPages = [`${customPath}/api/__keystone_api_build`, `${customPath}/api/auth/csrf`, `${customPath}/api/auth/signin`, `${customPath}/api/auth/callback`, `${customPath}/api/auth/session`, `${customPath}/api/auth/providers`, `${customPath}/api/auth/signout`, `${customPath}/api/auth/error`]; // TODO: Add Provider Types
310
+ // @ts-ignore
343
311
 
344
312
  function addPages(provider) {
345
313
  const name = provider.id;
@@ -357,8 +325,7 @@ function createAuth({
357
325
 
358
326
  const extendGraphqlSchema = getSchemaExtension({
359
327
  identityField,
360
- listKey,
361
- gqlNames
328
+ listKey
362
329
  });
363
330
  /**
364
331
  * validateConfig
@@ -372,7 +339,9 @@ function createAuth({
372
339
  if (listConfig === undefined) {
373
340
  const msg = `A createAuth() invocation specifies the list "${listKey}" but no list with that key has been defined.`;
374
341
  throw new Error(msg);
375
- } // TODO: Check for String-like typing for identityField? How?
342
+ } // TODO: Check if providers
343
+ // TODO: Check other required commands/data
344
+ // TODO: Check for String-like typing for identityField? How?
376
345
  // TODO: Validate that the identifyField is unique.
377
346
  // TODO: If this field isn't required, what happens if I try to log in as `null`?
378
347
 
@@ -380,9 +349,9 @@ function createAuth({
380
349
  const identityFieldConfig = listConfig.fields[identityField];
381
350
 
382
351
  if (identityFieldConfig === undefined) {
383
- const i = _JSON$stringify__default["default"](identityField);
352
+ const identityFieldName = _JSON$stringify__default["default"](identityField);
384
353
 
385
- const msg = `A createAuth() invocation for the "${listKey}" list specifies ${i} as its identityField but no field with that key exists on the list.`;
354
+ const msg = `A createAuth() invocation for the "${listKey}" list specifies ${identityFieldName} as its identityField but no field with that key exists on the list.`;
386
355
  throw new Error(msg);
387
356
  }
388
357
  };
@@ -405,7 +374,15 @@ function createAuth({
405
374
  sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
406
375
 
407
376
  return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
408
- start,
377
+ start: async ({
378
+ res
379
+ }) => {
380
+ console.log("start");
381
+ const session = await start({
382
+ res
383
+ });
384
+ return session;
385
+ },
409
386
  get: async ({
410
387
  req
411
388
  }) => {
@@ -413,16 +390,15 @@ function createAuth({
413
390
 
414
391
  const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
415
392
 
416
- if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
393
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/api/auth")) {
417
394
  return;
418
395
  }
419
396
 
420
- if (((_req$headers$authoriz = req.headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(' ')[0]) === 'Bearer') {
397
+ if (((_req$headers$authoriz = req.headers.authorization) === null || _req$headers$authoriz === void 0 ? void 0 : _req$headers$authoriz.split(" ")[0]) === "Bearer") {
421
398
  var _token$data;
422
399
 
423
- const request = req;
424
400
  const token = await jwt.getToken({
425
- req: request,
401
+ req,
426
402
  secret: sessionSecret
427
403
  });
428
404
 
@@ -443,14 +419,15 @@ function createAuth({
443
419
  res,
444
420
  req
445
421
  }) => {
446
- const TOKEN_NAME = '__Secure-next-auth.session-token' ;
447
- res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
422
+ const TOKEN_NAME = "__Secure-next-auth.session-token" ;
423
+ res.setHeader("Set-Cookie", cookie__namespace.serialize(TOKEN_NAME, "", {
448
424
  maxAge: 0,
449
425
  expires: new Date(),
450
426
  httpOnly: true,
451
- secure: "production" === 'production',
452
- path: '/',
453
- sameSite: 'lax',
427
+ secure: "production" === "production",
428
+ path: "/",
429
+ sameSite: "lax",
430
+ // TODO: Update parse to URL
454
431
  domain: url__default["default"].parse(req.url).hostname
455
432
  }));
456
433
  }
@@ -487,26 +464,32 @@ function createAuth({
487
464
  },
488
465
  enableSessionItem: true,
489
466
  isAccessAllowed: async context => {
490
- var _context$req2, _keystoneConfig$ui3;
491
- // even if the user isn't logged in (which should always be the case if they're seeing /init)
467
+ var _keystoneConfig$ui3;
468
+
469
+ const {
470
+ req
471
+ } = context;
472
+ const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname; // Allow nextjs scripts and static files to be accessed without auth
492
473
 
474
+ if (_includesInstanceProperty__default["default"](pathname).call(pathname, "/_next/")) {
475
+ return true;
476
+ } // Allow keystone to access /api/__keystone_api_build for hot reloading
493
477
 
494
- const headers = (_context$req2 = context.req) === null || _context$req2 === void 0 ? void 0 : _context$req2.headers;
495
- const host = headers ? headers['x-forwarded-host'] || headers.host : null;
496
- const thisUrl = headers !== null && headers !== void 0 && headers.referer ? new _URL__default["default"](headers.referer) : undefined;
497
- const accessingInitPage = (thisUrl === null || thisUrl === void 0 ? void 0 : thisUrl.pathname) === '/init' && (thisUrl === null || thisUrl === void 0 ? void 0 : thisUrl.host) === host && (await context.sudo().query[listKey].count({})) === 0;
498
- return accessingInitPage || ((_keystoneConfig$ui3 = keystoneConfig.ui) !== null && _keystoneConfig$ui3 !== void 0 && _keystoneConfig$ui3.isAccessAllowed ? keystoneConfig.ui.isAccessAllowed(context) : context.session !== undefined);
478
+ return (_keystoneConfig$ui3 = keystoneConfig.ui) !== null && _keystoneConfig$ui3 !== void 0 && _keystoneConfig$ui3.isAccessAllowed ? keystoneConfig.ui.isAccessAllowed(context) : context.session !== undefined;
499
479
  }
500
480
  });
501
481
  }
502
482
 
503
- if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
483
+ if (!keystoneConfig.session) throw new TypeError("Missing .session configuration");
504
484
  const session = withItemData(keystoneConfig.session);
505
485
  const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
506
486
  return _objectSpread(_objectSpread({}, keystoneConfig), {}, {
507
487
  ui,
508
- session,
488
+ cookies,
509
489
  providers,
490
+ pages,
491
+ resolver,
492
+ session,
510
493
  lists: _objectSpread({}, keystoneConfig.lists),
511
494
  experimental: _objectSpread(_objectSpread({}, keystoneConfig.experimental), {}, {
512
495
  generateNodeAPI: true