@opensaas/keystone-nextjs-auth 20.5.0 → 21.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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