@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.
- package/CHANGELOG.md +20 -0
- package/README.md +5 -3
- package/dist/declarations/src/gql/getBaseAuthSchema.d.ts +1 -3
- package/dist/declarations/src/index.d.ts +5 -5
- package/dist/declarations/src/pages/NextAuthPage.d.ts +16 -9
- package/dist/declarations/src/schema.d.ts +1 -3
- package/dist/declarations/src/templates/auth.d.ts +4 -12
- package/dist/declarations/src/types.d.ts +17 -20
- package/dist/opensaas-keystone-nextjs-auth.cjs.dev.js +77 -92
- package/dist/opensaas-keystone-nextjs-auth.cjs.prod.js +75 -92
- package/dist/opensaas-keystone-nextjs-auth.esm.js +77 -92
- package/package.json +8 -7
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.dev.js +37 -32
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js +37 -32
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.esm.js +37 -32
- package/src/gql/getBaseAuthSchema.ts +0 -4
- package/src/index.ts +96 -94
- package/src/pages/NextAuthPage.tsx +59 -38
- package/src/schema.ts +0 -22
- package/src/templates/auth.ts +11 -28
- package/src/templates/next-config.ts +3 -0
- package/src/types.ts +20 -21
- package/src/gql/getInitFirstItemSchema.ts +0 -81
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
182
|
+
autoCreate,
|
194
183
|
identityField,
|
195
|
-
sessionData,
|
196
184
|
listKey,
|
197
|
-
|
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
|
-
|
230
|
-
|
231
|
-
|
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
|
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:
|
246
|
+
kind: "redirect",
|
280
247
|
to: `${customPath}`
|
281
248
|
};
|
282
249
|
}
|
283
250
|
|
284
|
-
if (customPath !==
|
251
|
+
if (customPath !== "" && pathname === "/") {
|
285
252
|
return {
|
286
|
-
kind:
|
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:
|
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:
|
314
|
-
outputPath:
|
284
|
+
mode: "write",
|
285
|
+
outputPath: "pages/api/auth/[...nextauth].js",
|
315
286
|
src: authTemplate({
|
316
|
-
|
287
|
+
autoCreate,
|
317
288
|
identityField,
|
318
|
-
sessionData,
|
319
289
|
listKey,
|
320
|
-
|
321
|
-
userMap,
|
322
|
-
accountMap,
|
323
|
-
profileMap,
|
290
|
+
sessionData,
|
324
291
|
sessionSecret
|
325
292
|
})
|
326
293
|
}, {
|
327
|
-
mode:
|
328
|
-
outputPath:
|
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
|
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
|
352
|
+
const identityFieldName = _JSON$stringify__default["default"](identityField);
|
384
353
|
|
385
|
-
const msg = `A createAuth() invocation for the "${listKey}" list specifies ${
|
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,
|
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(
|
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
|
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 =
|
447
|
-
res.setHeader(
|
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" ===
|
452
|
-
path:
|
453
|
-
sameSite:
|
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
|
491
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|