@opensaas/keystone-nextjs-auth 21.1.1 → 22.0.0
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 +6 -0
- package/dist/declarations/src/index.d.ts +3 -3
- package/dist/declarations/src/pages/NextAuthPage.d.ts +7 -1
- package/dist/declarations/src/templates/next-config.d.ts +1 -1
- package/dist/declarations/src/types.d.ts +30 -4
- package/dist/opensaas-keystone-nextjs-auth.cjs.dev.js +25 -35
- package/dist/opensaas-keystone-nextjs-auth.cjs.prod.js +24 -34
- package/dist/opensaas-keystone-nextjs-auth.esm.js +25 -35
- package/package.json +1 -1
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.dev.js +25 -13
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js +25 -13
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.esm.js +25 -12
- package/src/gql/getBaseAuthSchema.ts +1 -4
- package/src/index.ts +70 -76
- package/src/lib/findMatchingIdentity.ts +1 -4
- package/src/pages/NextAuthPage.tsx +25 -33
- package/src/schema.ts +2 -4
- package/src/templates/next-config.ts +1 -5
- package/src/types.ts +29 -10
package/CHANGELOG.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
import { BaseListTypeInfo, KeystoneConfig } from
|
2
|
-
import { AuthConfig, KeystoneOAuthConfig } from
|
1
|
+
import { BaseListTypeInfo, KeystoneConfig } from '@keystone-6/core/types';
|
2
|
+
import { AuthConfig, KeystoneOAuthConfig } from './types';
|
3
3
|
/**
|
4
4
|
* createAuth function
|
5
5
|
*
|
6
6
|
* Generates config for Keystone to implement standard auth features.
|
7
7
|
*/
|
8
|
-
export type { NextAuthProviders, KeystoneOAuthConfig } from
|
8
|
+
export type { NextAuthProviders, KeystoneOAuthConfig } from './types';
|
9
9
|
export declare function createAuth<GeneratedListTypes extends BaseListTypeInfo>({ autoCreate, cookies, identityField, listKey, keystonePath, pages, resolver, providers, sessionData, sessionSecret, }: AuthConfig<GeneratedListTypes>): {
|
10
10
|
withAuth: (keystoneConfig: KeystoneConfig) => KeystoneOAuthConfig;
|
11
11
|
};
|
@@ -11,7 +11,13 @@ declare type CoreNextAuthPageProps = {
|
|
11
11
|
listKey: string;
|
12
12
|
pages?: Partial<PagesOptions>;
|
13
13
|
providers?: Provider[];
|
14
|
-
resolver?:
|
14
|
+
resolver?: (args: {
|
15
|
+
user: any;
|
16
|
+
profile: any;
|
17
|
+
account: any;
|
18
|
+
}) => {
|
19
|
+
[key: string]: boolean | string | number;
|
20
|
+
};
|
15
21
|
sessionData: string | undefined;
|
16
22
|
sessionSecret: string;
|
17
23
|
};
|
@@ -1,6 +1,26 @@
|
|
1
|
-
|
2
|
-
import {
|
1
|
+
/// <reference types="node" />
|
2
|
+
import type { ServerResponse, IncomingMessage } from 'http';
|
3
|
+
import type { NextRequest } from 'next/server';
|
3
4
|
import { Provider } from 'next-auth/providers';
|
5
|
+
import { CookiesOptions, PagesOptions } from 'next-auth';
|
6
|
+
import { BaseListTypeInfo, KeystoneConfig, CreateContext } from '@keystone-6/core/types';
|
7
|
+
declare type NextAuthResponse = IncomingMessage & NextRequest;
|
8
|
+
export declare type AuthSessionStrategy<StoredSessionData> = {
|
9
|
+
start: (args: {
|
10
|
+
res: ServerResponse;
|
11
|
+
data: any;
|
12
|
+
createContext: CreateContext;
|
13
|
+
}) => Promise<string>;
|
14
|
+
end: (args: {
|
15
|
+
req: IncomingMessage;
|
16
|
+
res: ServerResponse;
|
17
|
+
createContext: CreateContext;
|
18
|
+
}) => Promise<void>;
|
19
|
+
get: (args: {
|
20
|
+
req: NextAuthResponse;
|
21
|
+
createContext: CreateContext;
|
22
|
+
}) => Promise<StoredSessionData | undefined>;
|
23
|
+
};
|
4
24
|
export declare type NextAuthSession = {
|
5
25
|
listKey: string;
|
6
26
|
itemId: string;
|
@@ -27,11 +47,17 @@ export declare type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
|
|
27
47
|
identityField: GeneratedListTypes['fields'];
|
28
48
|
/** Path for Keystone interface */
|
29
49
|
keystonePath?: string;
|
30
|
-
pages?:
|
50
|
+
pages?: Partial<PagesOptions>;
|
31
51
|
/** Providers for Next Auth */
|
32
52
|
providers: NextAuthProviders;
|
33
53
|
/** Resolver for user to define their profile */
|
34
|
-
resolver?:
|
54
|
+
resolver?: (args: {
|
55
|
+
user: any;
|
56
|
+
profile: any;
|
57
|
+
account: any;
|
58
|
+
}) => Promise<{
|
59
|
+
[key: string]: boolean | string | number;
|
60
|
+
}>;
|
35
61
|
/** Session data population */
|
36
62
|
sessionData?: string | undefined;
|
37
63
|
/** Next-Auth Session Secret */
|
@@ -196,7 +196,7 @@ const authTemplate = ({
|
|
196
196
|
return authOut;
|
197
197
|
};
|
198
198
|
|
199
|
-
const _excluded = ["get"
|
199
|
+
const _excluded = ["get"];
|
200
200
|
/**
|
201
201
|
* createAuth function
|
202
202
|
*
|
@@ -219,7 +219,7 @@ function createAuth({
|
|
219
219
|
// part of the createAuth API (in which case its use cases need to be documented and tested)
|
220
220
|
// or whether always being true is what we want, in which case we can refactor our code
|
221
221
|
// to match this. -TL
|
222
|
-
const customPath = !keystonePath || keystonePath ===
|
222
|
+
const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
|
223
223
|
/**
|
224
224
|
* pageMiddleware
|
225
225
|
*
|
@@ -244,14 +244,14 @@ function createAuth({
|
|
244
244
|
if (isValidSession) {
|
245
245
|
if (pathname === `${customPath}/api/auth/signin`) {
|
246
246
|
return {
|
247
|
-
kind:
|
247
|
+
kind: 'redirect',
|
248
248
|
to: `${customPath}`
|
249
249
|
};
|
250
250
|
}
|
251
251
|
|
252
|
-
if (customPath !==
|
252
|
+
if (customPath !== '' && pathname === '/') {
|
253
253
|
return {
|
254
|
-
kind:
|
254
|
+
kind: 'redirect',
|
255
255
|
to: `${customPath}`
|
256
256
|
};
|
257
257
|
}
|
@@ -259,13 +259,13 @@ function createAuth({
|
|
259
259
|
return;
|
260
260
|
}
|
261
261
|
|
262
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
262
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/_next/') || _includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth/') || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || pages !== null && pages !== void 0 && pages.error && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || pages !== null && pages !== void 0 && pages.signOut && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
|
263
263
|
return;
|
264
264
|
}
|
265
265
|
|
266
266
|
if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
|
267
267
|
return {
|
268
|
-
kind:
|
268
|
+
kind: 'redirect',
|
269
269
|
to: (pages === null || pages === void 0 ? void 0 : pages.signIn) || `${customPath}/api/auth/signin`
|
270
270
|
};
|
271
271
|
}
|
@@ -282,8 +282,8 @@ function createAuth({
|
|
282
282
|
|
283
283
|
const getAdditionalFiles = () => {
|
284
284
|
const filesToWrite = [{
|
285
|
-
mode:
|
286
|
-
outputPath:
|
285
|
+
mode: 'write',
|
286
|
+
outputPath: 'pages/api/auth/[...nextauth].js',
|
287
287
|
src: authTemplate({
|
288
288
|
autoCreate,
|
289
289
|
identityField,
|
@@ -292,8 +292,8 @@ function createAuth({
|
|
292
292
|
sessionSecret
|
293
293
|
})
|
294
294
|
}, {
|
295
|
-
mode:
|
296
|
-
outputPath:
|
295
|
+
mode: 'write',
|
296
|
+
outputPath: 'next.config.js',
|
297
297
|
src: nextConfigTemplate({
|
298
298
|
keystonePath: customPath
|
299
299
|
})
|
@@ -368,34 +368,24 @@ function createAuth({
|
|
368
368
|
|
369
369
|
|
370
370
|
const withItemData = _sessionStrategy => {
|
371
|
-
const
|
372
|
-
get,
|
373
|
-
start
|
374
|
-
} = _sessionStrategy,
|
375
|
-
sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
371
|
+
const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
376
372
|
|
377
373
|
return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
|
378
|
-
start: async ({
|
379
|
-
|
380
|
-
}) => {
|
381
|
-
console.log("start");
|
382
|
-
const session = await start({
|
383
|
-
res
|
384
|
-
});
|
385
|
-
return session;
|
374
|
+
start: async () => {
|
375
|
+
return 'false';
|
386
376
|
},
|
387
377
|
get: async ({
|
388
378
|
req
|
389
379
|
}) => {
|
390
|
-
var _req$headers$authoriz;
|
380
|
+
var _req$headers, _req$headers$authoriz;
|
391
381
|
|
392
382
|
const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
|
393
383
|
|
394
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
384
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
|
395
385
|
return;
|
396
386
|
}
|
397
387
|
|
398
|
-
if (((_req$headers
|
388
|
+
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') {
|
399
389
|
var _token$data;
|
400
390
|
|
401
391
|
const token = await jwt.getToken({
|
@@ -420,14 +410,14 @@ function createAuth({
|
|
420
410
|
res,
|
421
411
|
req
|
422
412
|
}) => {
|
423
|
-
const TOKEN_NAME = process.env.NODE_ENV ===
|
424
|
-
res.setHeader(
|
413
|
+
const TOKEN_NAME = process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token';
|
414
|
+
res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
|
425
415
|
maxAge: 0,
|
426
416
|
expires: new Date(),
|
427
417
|
httpOnly: true,
|
428
|
-
secure: process.env.NODE_ENV ===
|
429
|
-
path:
|
430
|
-
sameSite:
|
418
|
+
secure: process.env.NODE_ENV === 'production',
|
419
|
+
path: '/',
|
420
|
+
sameSite: 'lax',
|
431
421
|
// TODO: Update parse to URL
|
432
422
|
domain: url__default["default"].parse(req.url).hostname
|
433
423
|
}));
|
@@ -472,12 +462,12 @@ function createAuth({
|
|
472
462
|
} = context;
|
473
463
|
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
|
474
464
|
|
475
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
465
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/_next/')) {
|
476
466
|
return true;
|
477
467
|
} // Allow keystone to access /api/__keystone_api_build for hot reloading
|
478
468
|
|
479
469
|
|
480
|
-
if (process.env.NODE_ENV !==
|
470
|
+
if (process.env.NODE_ENV !== 'production' && ((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url) !== undefined && new _URL__default["default"](context.req.url, 'http://example.com').pathname === `${customPath}/api/__keystone_api_build`) {
|
481
471
|
return true;
|
482
472
|
}
|
483
473
|
|
@@ -486,7 +476,7 @@ function createAuth({
|
|
486
476
|
});
|
487
477
|
}
|
488
478
|
|
489
|
-
if (!keystoneConfig.session) throw new TypeError(
|
479
|
+
if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
|
490
480
|
const session = withItemData(keystoneConfig.session);
|
491
481
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
492
482
|
return _objectSpread(_objectSpread({}, keystoneConfig), {}, {
|
@@ -195,7 +195,7 @@ const authTemplate = ({
|
|
195
195
|
return authOut;
|
196
196
|
};
|
197
197
|
|
198
|
-
const _excluded = ["get"
|
198
|
+
const _excluded = ["get"];
|
199
199
|
/**
|
200
200
|
* createAuth function
|
201
201
|
*
|
@@ -218,7 +218,7 @@ function createAuth({
|
|
218
218
|
// part of the createAuth API (in which case its use cases need to be documented and tested)
|
219
219
|
// or whether always being true is what we want, in which case we can refactor our code
|
220
220
|
// to match this. -TL
|
221
|
-
const customPath = !keystonePath || keystonePath ===
|
221
|
+
const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
|
222
222
|
/**
|
223
223
|
* pageMiddleware
|
224
224
|
*
|
@@ -243,14 +243,14 @@ function createAuth({
|
|
243
243
|
if (isValidSession) {
|
244
244
|
if (pathname === `${customPath}/api/auth/signin`) {
|
245
245
|
return {
|
246
|
-
kind:
|
246
|
+
kind: 'redirect',
|
247
247
|
to: `${customPath}`
|
248
248
|
};
|
249
249
|
}
|
250
250
|
|
251
|
-
if (customPath !==
|
251
|
+
if (customPath !== '' && pathname === '/') {
|
252
252
|
return {
|
253
|
-
kind:
|
253
|
+
kind: 'redirect',
|
254
254
|
to: `${customPath}`
|
255
255
|
};
|
256
256
|
}
|
@@ -258,13 +258,13 @@ function createAuth({
|
|
258
258
|
return;
|
259
259
|
}
|
260
260
|
|
261
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
261
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/_next/') || _includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth/') || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || pages !== null && pages !== void 0 && pages.error && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || pages !== null && pages !== void 0 && pages.signOut && _includesInstanceProperty__default["default"](pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
|
262
262
|
return;
|
263
263
|
}
|
264
264
|
|
265
265
|
if (!session && !_includesInstanceProperty__default["default"](pathname).call(pathname, `${customPath}/api/auth/`)) {
|
266
266
|
return {
|
267
|
-
kind:
|
267
|
+
kind: 'redirect',
|
268
268
|
to: (pages === null || pages === void 0 ? void 0 : pages.signIn) || `${customPath}/api/auth/signin`
|
269
269
|
};
|
270
270
|
}
|
@@ -281,8 +281,8 @@ function createAuth({
|
|
281
281
|
|
282
282
|
const getAdditionalFiles = () => {
|
283
283
|
const filesToWrite = [{
|
284
|
-
mode:
|
285
|
-
outputPath:
|
284
|
+
mode: 'write',
|
285
|
+
outputPath: 'pages/api/auth/[...nextauth].js',
|
286
286
|
src: authTemplate({
|
287
287
|
autoCreate,
|
288
288
|
identityField,
|
@@ -291,8 +291,8 @@ function createAuth({
|
|
291
291
|
sessionSecret
|
292
292
|
})
|
293
293
|
}, {
|
294
|
-
mode:
|
295
|
-
outputPath:
|
294
|
+
mode: 'write',
|
295
|
+
outputPath: 'next.config.js',
|
296
296
|
src: nextConfigTemplate({
|
297
297
|
keystonePath: customPath
|
298
298
|
})
|
@@ -367,34 +367,24 @@ function createAuth({
|
|
367
367
|
|
368
368
|
|
369
369
|
const withItemData = _sessionStrategy => {
|
370
|
-
const
|
371
|
-
get,
|
372
|
-
start
|
373
|
-
} = _sessionStrategy,
|
374
|
-
sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
370
|
+
const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
375
371
|
|
376
372
|
return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
|
377
|
-
start: async ({
|
378
|
-
|
379
|
-
}) => {
|
380
|
-
console.log("start");
|
381
|
-
const session = await start({
|
382
|
-
res
|
383
|
-
});
|
384
|
-
return session;
|
373
|
+
start: async () => {
|
374
|
+
return 'false';
|
385
375
|
},
|
386
376
|
get: async ({
|
387
377
|
req
|
388
378
|
}) => {
|
389
|
-
var _req$headers$authoriz;
|
379
|
+
var _req$headers, _req$headers$authoriz;
|
390
380
|
|
391
381
|
const pathname = url__default["default"].parse(req === null || req === void 0 ? void 0 : req.url).pathname;
|
392
382
|
|
393
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
383
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/api/auth')) {
|
394
384
|
return;
|
395
385
|
}
|
396
386
|
|
397
|
-
if (((_req$headers
|
387
|
+
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') {
|
398
388
|
var _token$data;
|
399
389
|
|
400
390
|
const token = await jwt.getToken({
|
@@ -419,14 +409,14 @@ function createAuth({
|
|
419
409
|
res,
|
420
410
|
req
|
421
411
|
}) => {
|
422
|
-
const TOKEN_NAME =
|
423
|
-
res.setHeader(
|
412
|
+
const TOKEN_NAME = '__Secure-next-auth.session-token' ;
|
413
|
+
res.setHeader('Set-Cookie', cookie__namespace.serialize(TOKEN_NAME, '', {
|
424
414
|
maxAge: 0,
|
425
415
|
expires: new Date(),
|
426
416
|
httpOnly: true,
|
427
|
-
secure: "production" ===
|
428
|
-
path:
|
429
|
-
sameSite:
|
417
|
+
secure: "production" === 'production',
|
418
|
+
path: '/',
|
419
|
+
sameSite: 'lax',
|
430
420
|
// TODO: Update parse to URL
|
431
421
|
domain: url__default["default"].parse(req.url).hostname
|
432
422
|
}));
|
@@ -471,7 +461,7 @@ function createAuth({
|
|
471
461
|
} = context;
|
472
462
|
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
|
473
463
|
|
474
|
-
if (_includesInstanceProperty__default["default"](pathname).call(pathname,
|
464
|
+
if (_includesInstanceProperty__default["default"](pathname).call(pathname, '/_next/')) {
|
475
465
|
return true;
|
476
466
|
} // Allow keystone to access /api/__keystone_api_build for hot reloading
|
477
467
|
|
@@ -480,7 +470,7 @@ function createAuth({
|
|
480
470
|
});
|
481
471
|
}
|
482
472
|
|
483
|
-
if (!keystoneConfig.session) throw new TypeError(
|
473
|
+
if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
|
484
474
|
const session = withItemData(keystoneConfig.session);
|
485
475
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
486
476
|
return _objectSpread(_objectSpread({}, keystoneConfig), {}, {
|
@@ -163,7 +163,7 @@ const authTemplate = ({
|
|
163
163
|
return authOut;
|
164
164
|
};
|
165
165
|
|
166
|
-
const _excluded = ["get"
|
166
|
+
const _excluded = ["get"];
|
167
167
|
/**
|
168
168
|
* createAuth function
|
169
169
|
*
|
@@ -186,7 +186,7 @@ function createAuth({
|
|
186
186
|
// part of the createAuth API (in which case its use cases need to be documented and tested)
|
187
187
|
// or whether always being true is what we want, in which case we can refactor our code
|
188
188
|
// to match this. -TL
|
189
|
-
const customPath = !keystonePath || keystonePath ===
|
189
|
+
const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
|
190
190
|
/**
|
191
191
|
* pageMiddleware
|
192
192
|
*
|
@@ -211,14 +211,14 @@ function createAuth({
|
|
211
211
|
if (isValidSession) {
|
212
212
|
if (pathname === `${customPath}/api/auth/signin`) {
|
213
213
|
return {
|
214
|
-
kind:
|
214
|
+
kind: 'redirect',
|
215
215
|
to: `${customPath}`
|
216
216
|
};
|
217
217
|
}
|
218
218
|
|
219
|
-
if (customPath !==
|
219
|
+
if (customPath !== '' && pathname === '/') {
|
220
220
|
return {
|
221
|
-
kind:
|
221
|
+
kind: 'redirect',
|
222
222
|
to: `${customPath}`
|
223
223
|
};
|
224
224
|
}
|
@@ -226,13 +226,13 @@ function createAuth({
|
|
226
226
|
return;
|
227
227
|
}
|
228
228
|
|
229
|
-
if (_includesInstanceProperty(pathname).call(pathname,
|
229
|
+
if (_includesInstanceProperty(pathname).call(pathname, '/_next/') || _includesInstanceProperty(pathname).call(pathname, '/api/auth/') || pages !== null && pages !== void 0 && pages.signIn && _includesInstanceProperty(pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signIn) || pages !== null && pages !== void 0 && pages.error && _includesInstanceProperty(pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.error) || pages !== null && pages !== void 0 && pages.signOut && _includesInstanceProperty(pathname).call(pathname, pages === null || pages === void 0 ? void 0 : pages.signOut)) {
|
230
230
|
return;
|
231
231
|
}
|
232
232
|
|
233
233
|
if (!session && !_includesInstanceProperty(pathname).call(pathname, `${customPath}/api/auth/`)) {
|
234
234
|
return {
|
235
|
-
kind:
|
235
|
+
kind: 'redirect',
|
236
236
|
to: (pages === null || pages === void 0 ? void 0 : pages.signIn) || `${customPath}/api/auth/signin`
|
237
237
|
};
|
238
238
|
}
|
@@ -249,8 +249,8 @@ function createAuth({
|
|
249
249
|
|
250
250
|
const getAdditionalFiles = () => {
|
251
251
|
const filesToWrite = [{
|
252
|
-
mode:
|
253
|
-
outputPath:
|
252
|
+
mode: 'write',
|
253
|
+
outputPath: 'pages/api/auth/[...nextauth].js',
|
254
254
|
src: authTemplate({
|
255
255
|
autoCreate,
|
256
256
|
identityField,
|
@@ -259,8 +259,8 @@ function createAuth({
|
|
259
259
|
sessionSecret
|
260
260
|
})
|
261
261
|
}, {
|
262
|
-
mode:
|
263
|
-
outputPath:
|
262
|
+
mode: 'write',
|
263
|
+
outputPath: 'next.config.js',
|
264
264
|
src: nextConfigTemplate({
|
265
265
|
keystonePath: customPath
|
266
266
|
})
|
@@ -335,34 +335,24 @@ function createAuth({
|
|
335
335
|
|
336
336
|
|
337
337
|
const withItemData = _sessionStrategy => {
|
338
|
-
const
|
339
|
-
get,
|
340
|
-
start
|
341
|
-
} = _sessionStrategy,
|
342
|
-
sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
338
|
+
const sessionStrategy = _objectWithoutProperties(_sessionStrategy, _excluded);
|
343
339
|
|
344
340
|
return _objectSpread(_objectSpread({}, sessionStrategy), {}, {
|
345
|
-
start: async ({
|
346
|
-
|
347
|
-
}) => {
|
348
|
-
console.log("start");
|
349
|
-
const session = await start({
|
350
|
-
res
|
351
|
-
});
|
352
|
-
return session;
|
341
|
+
start: async () => {
|
342
|
+
return 'false';
|
353
343
|
},
|
354
344
|
get: async ({
|
355
345
|
req
|
356
346
|
}) => {
|
357
|
-
var _req$headers$authoriz;
|
347
|
+
var _req$headers, _req$headers$authoriz;
|
358
348
|
|
359
349
|
const pathname = url.parse(req === null || req === void 0 ? void 0 : req.url).pathname;
|
360
350
|
|
361
|
-
if (_includesInstanceProperty(pathname).call(pathname,
|
351
|
+
if (_includesInstanceProperty(pathname).call(pathname, '/api/auth')) {
|
362
352
|
return;
|
363
353
|
}
|
364
354
|
|
365
|
-
if (((_req$headers
|
355
|
+
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') {
|
366
356
|
var _token$data;
|
367
357
|
|
368
358
|
const token = await getToken({
|
@@ -387,14 +377,14 @@ function createAuth({
|
|
387
377
|
res,
|
388
378
|
req
|
389
379
|
}) => {
|
390
|
-
const TOKEN_NAME = process.env.NODE_ENV ===
|
391
|
-
res.setHeader(
|
380
|
+
const TOKEN_NAME = process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token';
|
381
|
+
res.setHeader('Set-Cookie', cookie.serialize(TOKEN_NAME, '', {
|
392
382
|
maxAge: 0,
|
393
383
|
expires: new Date(),
|
394
384
|
httpOnly: true,
|
395
|
-
secure: process.env.NODE_ENV ===
|
396
|
-
path:
|
397
|
-
sameSite:
|
385
|
+
secure: process.env.NODE_ENV === 'production',
|
386
|
+
path: '/',
|
387
|
+
sameSite: 'lax',
|
398
388
|
// TODO: Update parse to URL
|
399
389
|
domain: url.parse(req.url).hostname
|
400
390
|
}));
|
@@ -439,12 +429,12 @@ function createAuth({
|
|
439
429
|
} = context;
|
440
430
|
const pathname = url.parse(req === null || req === void 0 ? void 0 : req.url).pathname; // Allow nextjs scripts and static files to be accessed without auth
|
441
431
|
|
442
|
-
if (_includesInstanceProperty(pathname).call(pathname,
|
432
|
+
if (_includesInstanceProperty(pathname).call(pathname, '/_next/')) {
|
443
433
|
return true;
|
444
434
|
} // Allow keystone to access /api/__keystone_api_build for hot reloading
|
445
435
|
|
446
436
|
|
447
|
-
if (process.env.NODE_ENV !==
|
437
|
+
if (process.env.NODE_ENV !== 'production' && ((_context$req = context.req) === null || _context$req === void 0 ? void 0 : _context$req.url) !== undefined && new _URL(context.req.url, 'http://example.com').pathname === `${customPath}/api/__keystone_api_build`) {
|
448
438
|
return true;
|
449
439
|
}
|
450
440
|
|
@@ -453,7 +443,7 @@ function createAuth({
|
|
453
443
|
});
|
454
444
|
}
|
455
445
|
|
456
|
-
if (!keystoneConfig.session) throw new TypeError(
|
446
|
+
if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
|
457
447
|
const session = withItemData(keystoneConfig.session);
|
458
448
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
459
449
|
return _objectSpread(_objectSpread({}, keystoneConfig), {}, {
|
package/package.json
CHANGED
@@ -3,12 +3,10 @@
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
4
4
|
|
5
5
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
6
|
-
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
7
6
|
var NextAuth = require('next-auth');
|
8
7
|
|
9
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
10
9
|
|
11
|
-
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
12
10
|
var NextAuth__default = /*#__PURE__*/_interopDefault(NextAuth);
|
13
11
|
|
14
12
|
async function findMatchingIdentity(identityField, identity, queryAPI) {
|
@@ -70,9 +68,7 @@ function NextAuthPage(props) {
|
|
70
68
|
resolver,
|
71
69
|
sessionData,
|
72
70
|
sessionSecret
|
73
|
-
} = props;
|
74
|
-
|
75
|
-
console.log('NextAuthPages... ', pages);
|
71
|
+
} = props;
|
76
72
|
|
77
73
|
if (!query) {
|
78
74
|
console.error('NextAuthPage got no query.');
|
@@ -123,26 +119,42 @@ function NextAuthPage(props) {
|
|
123
119
|
|
124
120
|
if (!result.success) {
|
125
121
|
if (!autoCreate) {
|
126
|
-
console.log('`autoCreate`
|
122
|
+
console.log('`autoCreate` is set to `false`, skipping user auto-creation');
|
127
123
|
return false;
|
128
124
|
}
|
129
125
|
|
130
|
-
console.log('`autoCreate`
|
126
|
+
console.log('`autoCreate` is set to `true`, auto-creating a new user');
|
131
127
|
const createUser = await list.createOne({
|
132
128
|
data
|
133
129
|
}).then(returned => {
|
134
|
-
|
135
|
-
|
130
|
+
return {
|
131
|
+
success: true,
|
132
|
+
user: returned
|
133
|
+
};
|
136
134
|
}).catch(error => {
|
137
135
|
console.log(error);
|
138
136
|
throw new Error(error);
|
139
137
|
});
|
140
138
|
console.log('Created User', createUser);
|
141
|
-
return createUser;
|
142
|
-
}
|
143
|
-
|
139
|
+
return createUser.success;
|
140
|
+
}
|
144
141
|
|
145
|
-
|
142
|
+
console.log('Data', data);
|
143
|
+
const updateUser = await list.updateOne({
|
144
|
+
where: {
|
145
|
+
id: result.item.id
|
146
|
+
},
|
147
|
+
data
|
148
|
+
}).then(returned => {
|
149
|
+
return {
|
150
|
+
success: true,
|
151
|
+
user: returned
|
152
|
+
};
|
153
|
+
}).catch(error => {
|
154
|
+
console.log(error);
|
155
|
+
throw new Error(error);
|
156
|
+
});
|
157
|
+
return updateUser.success;
|
146
158
|
},
|
147
159
|
|
148
160
|
async redirect({
|
package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js
CHANGED
@@ -3,12 +3,10 @@
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
4
4
|
|
5
5
|
var _objectSpread = require('@babel/runtime/helpers/objectSpread2');
|
6
|
-
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
7
6
|
var NextAuth = require('next-auth');
|
8
7
|
|
9
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
10
9
|
|
11
|
-
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
12
10
|
var NextAuth__default = /*#__PURE__*/_interopDefault(NextAuth);
|
13
11
|
|
14
12
|
async function findMatchingIdentity(identityField, identity, queryAPI) {
|
@@ -70,9 +68,7 @@ function NextAuthPage(props) {
|
|
70
68
|
resolver,
|
71
69
|
sessionData,
|
72
70
|
sessionSecret
|
73
|
-
} = props;
|
74
|
-
|
75
|
-
console.log('NextAuthPages... ', pages);
|
71
|
+
} = props;
|
76
72
|
|
77
73
|
if (!query) {
|
78
74
|
console.error('NextAuthPage got no query.');
|
@@ -123,26 +119,42 @@ function NextAuthPage(props) {
|
|
123
119
|
|
124
120
|
if (!result.success) {
|
125
121
|
if (!autoCreate) {
|
126
|
-
console.log('`autoCreate`
|
122
|
+
console.log('`autoCreate` is set to `false`, skipping user auto-creation');
|
127
123
|
return false;
|
128
124
|
}
|
129
125
|
|
130
|
-
console.log('`autoCreate`
|
126
|
+
console.log('`autoCreate` is set to `true`, auto-creating a new user');
|
131
127
|
const createUser = await list.createOne({
|
132
128
|
data
|
133
129
|
}).then(returned => {
|
134
|
-
|
135
|
-
|
130
|
+
return {
|
131
|
+
success: true,
|
132
|
+
user: returned
|
133
|
+
};
|
136
134
|
}).catch(error => {
|
137
135
|
console.log(error);
|
138
136
|
throw new Error(error);
|
139
137
|
});
|
140
138
|
console.log('Created User', createUser);
|
141
|
-
return createUser;
|
142
|
-
}
|
143
|
-
|
139
|
+
return createUser.success;
|
140
|
+
}
|
144
141
|
|
145
|
-
|
142
|
+
console.log('Data', data);
|
143
|
+
const updateUser = await list.updateOne({
|
144
|
+
where: {
|
145
|
+
id: result.item.id
|
146
|
+
},
|
147
|
+
data
|
148
|
+
}).then(returned => {
|
149
|
+
return {
|
150
|
+
success: true,
|
151
|
+
user: returned
|
152
|
+
};
|
153
|
+
}).catch(error => {
|
154
|
+
console.log(error);
|
155
|
+
throw new Error(error);
|
156
|
+
});
|
157
|
+
return updateUser.success;
|
146
158
|
},
|
147
159
|
|
148
160
|
async redirect({
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
|
2
|
-
import _JSON$stringify from '@babel/runtime-corejs3/core-js-stable/json/stringify';
|
3
2
|
import NextAuth from 'next-auth';
|
4
3
|
|
5
4
|
async function findMatchingIdentity(identityField, identity, queryAPI) {
|
@@ -61,9 +60,7 @@ function NextAuthPage(props) {
|
|
61
60
|
resolver,
|
62
61
|
sessionData,
|
63
62
|
sessionSecret
|
64
|
-
} = props;
|
65
|
-
|
66
|
-
console.log('NextAuthPages... ', pages);
|
63
|
+
} = props;
|
67
64
|
|
68
65
|
if (!query) {
|
69
66
|
console.error('NextAuthPage got no query.');
|
@@ -114,26 +111,42 @@ function NextAuthPage(props) {
|
|
114
111
|
|
115
112
|
if (!result.success) {
|
116
113
|
if (!autoCreate) {
|
117
|
-
console.log('`autoCreate`
|
114
|
+
console.log('`autoCreate` is set to `false`, skipping user auto-creation');
|
118
115
|
return false;
|
119
116
|
}
|
120
117
|
|
121
|
-
console.log('`autoCreate`
|
118
|
+
console.log('`autoCreate` is set to `true`, auto-creating a new user');
|
122
119
|
const createUser = await list.createOne({
|
123
120
|
data
|
124
121
|
}).then(returned => {
|
125
|
-
|
126
|
-
|
122
|
+
return {
|
123
|
+
success: true,
|
124
|
+
user: returned
|
125
|
+
};
|
127
126
|
}).catch(error => {
|
128
127
|
console.log(error);
|
129
128
|
throw new Error(error);
|
130
129
|
});
|
131
130
|
console.log('Created User', createUser);
|
132
|
-
return createUser;
|
133
|
-
}
|
134
|
-
|
131
|
+
return createUser.success;
|
132
|
+
}
|
135
133
|
|
136
|
-
|
134
|
+
console.log('Data', data);
|
135
|
+
const updateUser = await list.updateOne({
|
136
|
+
where: {
|
137
|
+
id: result.item.id
|
138
|
+
},
|
139
|
+
data
|
140
|
+
}).then(returned => {
|
141
|
+
return {
|
142
|
+
success: true,
|
143
|
+
user: returned
|
144
|
+
};
|
145
|
+
}).catch(error => {
|
146
|
+
console.log(error);
|
147
|
+
throw new Error(error);
|
148
|
+
});
|
149
|
+
return updateUser.success;
|
137
150
|
},
|
138
151
|
|
139
152
|
async redirect({
|
@@ -17,10 +17,7 @@ export function getBaseAuthSchema({
|
|
17
17
|
resolveType: (root, context) => context.session?.listKey,
|
18
18
|
}),
|
19
19
|
resolve(root, args, { session, db }) {
|
20
|
-
if (
|
21
|
-
typeof session?.itemId === 'string' &&
|
22
|
-
typeof session.listKey === 'string'
|
23
|
-
) {
|
20
|
+
if (typeof session?.itemId === 'string' && typeof session.listKey === 'string') {
|
24
21
|
return db[session.listKey].findOne({
|
25
22
|
where: { id: session.itemId },
|
26
23
|
});
|
package/src/index.ts
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
import url from
|
1
|
+
import url from 'url';
|
2
2
|
import {
|
3
3
|
AdminFileToWrite,
|
4
4
|
BaseListTypeInfo,
|
5
5
|
KeystoneConfig,
|
6
6
|
KeystoneContext,
|
7
7
|
AdminUIConfig,
|
8
|
-
SessionStrategy,
|
9
8
|
BaseKeystoneTypeInfo,
|
10
|
-
|
11
|
-
|
12
|
-
import {
|
13
|
-
import {
|
9
|
+
SessionStrategy,
|
10
|
+
} from '@keystone-6/core/types';
|
11
|
+
import { getSession } from 'next-auth/react';
|
12
|
+
import { getToken } from 'next-auth/jwt';
|
13
|
+
import { Provider } from 'next-auth/providers';
|
14
14
|
|
15
|
-
import * as cookie from
|
15
|
+
import * as cookie from 'cookie';
|
16
16
|
|
17
|
-
import { nextConfigTemplate } from
|
17
|
+
import { nextConfigTemplate } from './templates/next-config';
|
18
18
|
// import * as Path from 'path';
|
19
19
|
|
20
|
-
import { AuthConfig, KeystoneOAuthConfig, NextAuthSession } from
|
21
|
-
import { getSchemaExtension } from
|
22
|
-
import { authTemplate } from
|
20
|
+
import { AuthConfig, KeystoneOAuthConfig, NextAuthSession, AuthSessionStrategy } from './types';
|
21
|
+
import { getSchemaExtension } from './schema';
|
22
|
+
import { authTemplate } from './templates/auth';
|
23
23
|
|
24
24
|
/**
|
25
25
|
* createAuth function
|
@@ -27,7 +27,7 @@ import { authTemplate } from "./templates/auth";
|
|
27
27
|
* Generates config for Keystone to implement standard auth features.
|
28
28
|
*/
|
29
29
|
|
30
|
-
export type { NextAuthProviders, KeystoneOAuthConfig } from
|
30
|
+
export type { NextAuthProviders, KeystoneOAuthConfig } from './types';
|
31
31
|
export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
32
32
|
autoCreate,
|
33
33
|
cookies,
|
@@ -45,7 +45,7 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
45
45
|
// or whether always being true is what we want, in which case we can refactor our code
|
46
46
|
// to match this. -TL
|
47
47
|
|
48
|
-
const customPath = !keystonePath || keystonePath ===
|
48
|
+
const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
|
49
49
|
/**
|
50
50
|
* pageMiddleware
|
51
51
|
*
|
@@ -56,36 +56,38 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
56
56
|
* - to the init page when initFirstItem is configured, and there are no user in the database
|
57
57
|
* - to the signin page when no valid session is present
|
58
58
|
*/
|
59
|
-
const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>[
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>['pageMiddleware'] = async ({
|
60
|
+
context,
|
61
|
+
isValidSession,
|
62
|
+
}) => {
|
63
|
+
const { req, session } = context;
|
64
|
+
const pathname = url.parse(req?.url!).pathname!;
|
63
65
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
}
|
68
|
-
if (customPath !== "" && pathname === "/") {
|
69
|
-
return { kind: "redirect", to: `${customPath}` };
|
70
|
-
}
|
71
|
-
return;
|
72
|
-
}
|
73
|
-
if (
|
74
|
-
pathname.includes("/_next/") ||
|
75
|
-
pathname.includes("/api/auth/") ||
|
76
|
-
pathname.includes(pages?.signIn) ||
|
77
|
-
pathname.includes(pages?.error) ||
|
78
|
-
pathname.includes(pages?.signOut)
|
79
|
-
) {
|
80
|
-
return;
|
66
|
+
if (isValidSession) {
|
67
|
+
if (pathname === `${customPath}/api/auth/signin`) {
|
68
|
+
return { kind: 'redirect', to: `${customPath}` };
|
81
69
|
}
|
82
|
-
if (
|
83
|
-
return {
|
84
|
-
kind: "redirect",
|
85
|
-
to: pages?.signIn || `${customPath}/api/auth/signin`,
|
86
|
-
};
|
70
|
+
if (customPath !== '' && pathname === '/') {
|
71
|
+
return { kind: 'redirect', to: `${customPath}` };
|
87
72
|
}
|
88
|
-
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
if (
|
76
|
+
pathname.includes('/_next/') ||
|
77
|
+
pathname.includes('/api/auth/') ||
|
78
|
+
(pages?.signIn && pathname.includes(pages?.signIn)) ||
|
79
|
+
(pages?.error && pathname.includes(pages?.error)) ||
|
80
|
+
(pages?.signOut && pathname.includes(pages?.signOut))
|
81
|
+
) {
|
82
|
+
return;
|
83
|
+
}
|
84
|
+
if (!session && !pathname.includes(`${customPath}/api/auth/`)) {
|
85
|
+
return {
|
86
|
+
kind: 'redirect',
|
87
|
+
to: pages?.signIn || `${customPath}/api/auth/signin`,
|
88
|
+
};
|
89
|
+
}
|
90
|
+
};
|
89
91
|
|
90
92
|
/**
|
91
93
|
* getAdditionalFiles
|
@@ -98,8 +100,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
98
100
|
const getAdditionalFiles = () => {
|
99
101
|
const filesToWrite: AdminFileToWrite[] = [
|
100
102
|
{
|
101
|
-
mode:
|
102
|
-
outputPath:
|
103
|
+
mode: 'write',
|
104
|
+
outputPath: 'pages/api/auth/[...nextauth].js',
|
103
105
|
src: authTemplate({
|
104
106
|
autoCreate,
|
105
107
|
identityField,
|
@@ -109,8 +111,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
109
111
|
}),
|
110
112
|
},
|
111
113
|
{
|
112
|
-
mode:
|
113
|
-
outputPath:
|
114
|
+
mode: 'write',
|
115
|
+
outputPath: 'next.config.js',
|
114
116
|
src: nextConfigTemplate({ keystonePath: customPath }),
|
115
117
|
},
|
116
118
|
];
|
@@ -186,23 +188,20 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
186
188
|
- [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
|
187
189
|
*/
|
188
190
|
const withItemData = (
|
189
|
-
_sessionStrategy:
|
190
|
-
):
|
191
|
-
const { get,
|
191
|
+
_sessionStrategy: AuthSessionStrategy<Record<string, any>>
|
192
|
+
): AuthSessionStrategy<NextAuthSession | never> => {
|
193
|
+
const { get, ...sessionStrategy } = _sessionStrategy;
|
192
194
|
return {
|
193
195
|
...sessionStrategy,
|
194
|
-
start: async (
|
195
|
-
|
196
|
-
|
197
|
-
const session = await start({ res });
|
198
|
-
return session;
|
196
|
+
start: async () => {
|
197
|
+
return 'false';
|
199
198
|
},
|
200
199
|
get: async ({ req }) => {
|
201
200
|
const pathname = url.parse(req?.url!).pathname!;
|
202
|
-
if (pathname.includes(
|
201
|
+
if (pathname.includes('/api/auth')) {
|
203
202
|
return;
|
204
203
|
}
|
205
|
-
if (req.headers
|
204
|
+
if (req.headers?.authorization?.split(' ')[0] === 'Bearer') {
|
206
205
|
const token = (await getToken({
|
207
206
|
req,
|
208
207
|
secret: sessionSecret,
|
@@ -220,18 +219,18 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
220
219
|
},
|
221
220
|
end: async ({ res, req }) => {
|
222
221
|
const TOKEN_NAME =
|
223
|
-
process.env.NODE_ENV ===
|
224
|
-
?
|
225
|
-
:
|
222
|
+
process.env.NODE_ENV === 'production'
|
223
|
+
? '__Secure-next-auth.session-token'
|
224
|
+
: 'next-auth.session-token';
|
226
225
|
res.setHeader(
|
227
|
-
|
228
|
-
cookie.serialize(TOKEN_NAME,
|
226
|
+
'Set-Cookie',
|
227
|
+
cookie.serialize(TOKEN_NAME, '', {
|
229
228
|
maxAge: 0,
|
230
229
|
expires: new Date(),
|
231
230
|
httpOnly: true,
|
232
|
-
secure: process.env.NODE_ENV ===
|
233
|
-
path:
|
234
|
-
sameSite:
|
231
|
+
secure: process.env.NODE_ENV === 'production',
|
232
|
+
path: '/',
|
233
|
+
sameSite: 'lax',
|
235
234
|
// TODO: Update parse to URL
|
236
235
|
domain: url.parse(req.url as string).hostname as string,
|
237
236
|
})
|
@@ -257,28 +256,24 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
257
256
|
ui = {
|
258
257
|
...keystoneConfig.ui,
|
259
258
|
publicPages: [...(keystoneConfig.ui.publicPages || []), ...publicPages],
|
260
|
-
getAdditionalFiles: [
|
261
|
-
|
262
|
-
|
263
|
-
],
|
264
|
-
pageMiddleware: async (args) =>
|
265
|
-
(await pageMiddleware(args)) ??
|
266
|
-
keystoneConfig?.ui?.pageMiddleware?.(args),
|
259
|
+
getAdditionalFiles: [...(keystoneConfig.ui?.getAdditionalFiles || []), getAdditionalFiles],
|
260
|
+
pageMiddleware: async args =>
|
261
|
+
(await pageMiddleware(args)) ?? keystoneConfig?.ui?.pageMiddleware?.(args),
|
267
262
|
enableSessionItem: true,
|
268
263
|
isAccessAllowed: async (context: KeystoneContext) => {
|
269
264
|
const { req } = context;
|
270
265
|
const pathname = url.parse(req?.url!).pathname!;
|
271
266
|
|
272
267
|
// Allow nextjs scripts and static files to be accessed without auth
|
273
|
-
if (pathname.includes(
|
268
|
+
if (pathname.includes('/_next/')) {
|
274
269
|
return true;
|
275
270
|
}
|
276
271
|
|
277
272
|
// Allow keystone to access /api/__keystone_api_build for hot reloading
|
278
273
|
if (
|
279
|
-
process.env.NODE_ENV !==
|
274
|
+
process.env.NODE_ENV !== 'production' &&
|
280
275
|
context.req?.url !== undefined &&
|
281
|
-
new URL(context.req.url,
|
276
|
+
new URL(context.req.url, 'http://example.com').pathname ===
|
282
277
|
`${customPath}/api/__keystone_api_build`
|
283
278
|
) {
|
284
279
|
return true;
|
@@ -291,9 +286,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
291
286
|
};
|
292
287
|
}
|
293
288
|
|
294
|
-
if (!keystoneConfig.session)
|
295
|
-
|
296
|
-
const session = withItemData(keystoneConfig.session);
|
289
|
+
if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
|
290
|
+
const session = withItemData(keystoneConfig.session) as SessionStrategy<any>;
|
297
291
|
|
298
292
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
299
293
|
return {
|
@@ -312,7 +306,7 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
312
306
|
generateNodeAPI: true,
|
313
307
|
},
|
314
308
|
extendGraphqlSchema: existingExtendGraphQLSchema
|
315
|
-
?
|
309
|
+
? schema => existingExtendGraphQLSchema(extendGraphqlSchema(schema))
|
316
310
|
: extendGraphqlSchema,
|
317
311
|
};
|
318
312
|
};
|
@@ -4,10 +4,7 @@ export async function findMatchingIdentity(
|
|
4
4
|
identityField: string,
|
5
5
|
identity: string | number,
|
6
6
|
queryAPI: any
|
7
|
-
): Promise<
|
8
|
-
| { success: false; code: AuthTokenRequestErrorCode }
|
9
|
-
| { success: true; item: any }
|
10
|
-
> {
|
7
|
+
): Promise<{ success: false; code: AuthTokenRequestErrorCode } | { success: true; item: any }> {
|
11
8
|
const item = await queryAPI.findOne({
|
12
9
|
where: { [identityField]: identity },
|
13
10
|
});
|
@@ -1,14 +1,9 @@
|
|
1
|
-
import NextAuth, {
|
2
|
-
CookiesOptions,
|
3
|
-
EventCallbacks,
|
4
|
-
PagesOptions,
|
5
|
-
} from 'next-auth';
|
1
|
+
import NextAuth, { CookiesOptions, EventCallbacks, PagesOptions } from 'next-auth';
|
6
2
|
import type { KeystoneListsAPI } from '@keystone-6/core/types';
|
7
3
|
import { Provider } from 'next-auth/providers';
|
8
4
|
import { JWTOptions } from 'next-auth/jwt';
|
9
5
|
import { validateNextAuth } from '../lib/validateNextAuth';
|
10
6
|
|
11
|
-
// TODO: See if possible to merge with `type AuthConfig`
|
12
7
|
type CoreNextAuthPageProps = {
|
13
8
|
autoCreate: boolean;
|
14
9
|
cookies?: Partial<CookiesOptions>;
|
@@ -18,7 +13,9 @@ type CoreNextAuthPageProps = {
|
|
18
13
|
listKey: string;
|
19
14
|
pages?: Partial<PagesOptions>;
|
20
15
|
providers?: Provider[];
|
21
|
-
resolver?:
|
16
|
+
resolver?: (args: { user: any; profile: any; account: any }) => {
|
17
|
+
[key: string]: boolean | string | number;
|
18
|
+
};
|
22
19
|
sessionData: string | undefined;
|
23
20
|
sessionSecret: string;
|
24
21
|
};
|
@@ -45,8 +42,6 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
45
42
|
sessionData,
|
46
43
|
sessionSecret,
|
47
44
|
} = props;
|
48
|
-
// TODO: (v1.1). https://github.com/ijsto/keystone-6-oauth/projects/1#card-78602004
|
49
|
-
console.log('NextAuthPages... ', pages);
|
50
45
|
|
51
46
|
if (!query) {
|
52
47
|
console.error('NextAuthPage got no query.');
|
@@ -79,16 +74,9 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
79
74
|
} else {
|
80
75
|
identity = 0;
|
81
76
|
}
|
82
|
-
const userInput = resolver
|
83
|
-
? await resolver({ user, account, profile })
|
84
|
-
: {};
|
77
|
+
const userInput = resolver ? await resolver({ user, account, profile }) : {};
|
85
78
|
|
86
|
-
const result = await validateNextAuth(
|
87
|
-
identityField,
|
88
|
-
identity,
|
89
|
-
protectIdentities,
|
90
|
-
queryAPI
|
91
|
-
);
|
79
|
+
const result = await validateNextAuth(identityField, identity, protectIdentities, queryAPI);
|
92
80
|
// ID
|
93
81
|
const data: any = {
|
94
82
|
[identityField]: identity,
|
@@ -97,30 +85,35 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
97
85
|
|
98
86
|
if (!result.success) {
|
99
87
|
if (!autoCreate) {
|
100
|
-
console.log(
|
101
|
-
'`autoCreate` if set to `false`, skipping user auto-creation'
|
102
|
-
);
|
88
|
+
console.log('`autoCreate` is set to `false`, skipping user auto-creation');
|
103
89
|
return false;
|
104
90
|
}
|
105
|
-
console.log(
|
106
|
-
'`autoCreate` if set to `true`, auto-creating a new user'
|
107
|
-
);
|
91
|
+
console.log('`autoCreate` is set to `true`, auto-creating a new user');
|
108
92
|
|
109
93
|
const createUser = await list
|
110
94
|
.createOne({ data })
|
111
|
-
.then(
|
112
|
-
|
113
|
-
return true;
|
95
|
+
.then(returned => {
|
96
|
+
return { success: true, user: returned };
|
114
97
|
})
|
115
|
-
.catch(
|
98
|
+
.catch(error => {
|
116
99
|
console.log(error);
|
117
100
|
throw new Error(error);
|
118
101
|
});
|
119
102
|
console.log('Created User', createUser);
|
120
|
-
return createUser;
|
103
|
+
return createUser.success;
|
121
104
|
}
|
122
|
-
|
123
|
-
|
105
|
+
console.log('Data', data);
|
106
|
+
|
107
|
+
const updateUser = await list
|
108
|
+
.updateOne({ where: { id: result.item.id }, data })
|
109
|
+
.then(returned => {
|
110
|
+
return { success: true, user: returned };
|
111
|
+
})
|
112
|
+
.catch(error => {
|
113
|
+
console.log(error);
|
114
|
+
throw new Error(error);
|
115
|
+
});
|
116
|
+
return updateUser.success;
|
124
117
|
},
|
125
118
|
async redirect({ url }) {
|
126
119
|
return url;
|
@@ -167,5 +160,4 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
167
160
|
});
|
168
161
|
}
|
169
162
|
|
170
|
-
export const getNextAuthPage = (props: NextAuthPageProps) => () =>
|
171
|
-
NextAuthPage({ ...props });
|
163
|
+
export const getNextAuthPage = (props: NextAuthPageProps) => () => NextAuthPage({ ...props });
|
package/src/schema.ts
CHANGED
@@ -9,13 +9,11 @@ export const getSchemaExtension = ({
|
|
9
9
|
identityField: string;
|
10
10
|
listKey: string;
|
11
11
|
}): ExtendGraphqlSchema =>
|
12
|
-
graphql.extend(
|
12
|
+
graphql.extend(base => {
|
13
13
|
const baseSchema = getBaseAuthSchema({
|
14
14
|
listKey,
|
15
15
|
base,
|
16
16
|
});
|
17
17
|
|
18
|
-
return [baseSchema.extension].filter(
|
19
|
-
(x): x is Exclude<typeof x, undefined> => x !== undefined
|
20
|
-
);
|
18
|
+
return [baseSchema.extension].filter((x): x is Exclude<typeof x, undefined> => x !== undefined);
|
21
19
|
});
|
@@ -56,11 +56,7 @@ module.exports = withPreconstruct({
|
|
56
56
|
<% } %>
|
57
57
|
});
|
58
58
|
`;
|
59
|
-
export const nextConfigTemplate = ({
|
60
|
-
keystonePath,
|
61
|
-
}: {
|
62
|
-
keystonePath: string;
|
63
|
-
}) => {
|
59
|
+
export const nextConfigTemplate = ({ keystonePath }: { keystonePath: string }) => {
|
64
60
|
const nextConfigOut = ejs.render(template, { keystonePath });
|
65
61
|
|
66
62
|
return nextConfigOut;
|
package/src/types.ts
CHANGED
@@ -1,6 +1,27 @@
|
|
1
|
-
import {
|
2
|
-
import {
|
1
|
+
import type { ServerResponse, IncomingMessage } from 'http';
|
2
|
+
import type { NextRequest } from 'next/server';
|
3
3
|
import { Provider } from 'next-auth/providers';
|
4
|
+
import { CookiesOptions, PagesOptions } from 'next-auth';
|
5
|
+
import { BaseListTypeInfo, KeystoneConfig, CreateContext } from '@keystone-6/core/types';
|
6
|
+
|
7
|
+
type NextAuthResponse = IncomingMessage & NextRequest;
|
8
|
+
|
9
|
+
export declare type AuthSessionStrategy<StoredSessionData> = {
|
10
|
+
start: (args: {
|
11
|
+
res: ServerResponse;
|
12
|
+
data: any;
|
13
|
+
createContext: CreateContext;
|
14
|
+
}) => Promise<string>;
|
15
|
+
end: (args: {
|
16
|
+
req: IncomingMessage;
|
17
|
+
res: ServerResponse;
|
18
|
+
createContext: CreateContext;
|
19
|
+
}) => Promise<void>;
|
20
|
+
get: (args: {
|
21
|
+
req: NextAuthResponse;
|
22
|
+
createContext: CreateContext;
|
23
|
+
}) => Promise<StoredSessionData | undefined>;
|
24
|
+
};
|
4
25
|
|
5
26
|
export type NextAuthSession = { listKey: string; itemId: string; data: any };
|
6
27
|
|
@@ -15,9 +36,7 @@ type NextAuthOptions = {
|
|
15
36
|
resolver: any;
|
16
37
|
};
|
17
38
|
|
18
|
-
export type KeystoneOAuthConfig = KeystoneConfig &
|
19
|
-
KeytoneOAuthOptions &
|
20
|
-
NextAuthOptions;
|
39
|
+
export type KeystoneOAuthConfig = KeystoneConfig & KeytoneOAuthOptions & NextAuthOptions;
|
21
40
|
|
22
41
|
export type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
|
23
42
|
/** Auth Create users in Keystone DB from Auth Provider */
|
@@ -31,20 +50,20 @@ export type AuthConfig<GeneratedListTypes extends BaseListTypeInfo> = {
|
|
31
50
|
/** Path for Keystone interface */
|
32
51
|
keystonePath?: string;
|
33
52
|
// Custom pages for different NextAuth events
|
34
|
-
pages?:
|
53
|
+
pages?: Partial<PagesOptions>;
|
35
54
|
/** Providers for Next Auth */
|
36
55
|
providers: NextAuthProviders;
|
37
56
|
/** Resolver for user to define their profile */
|
38
|
-
resolver?:
|
57
|
+
resolver?: (args: { user: any; profile: any; account: any }) => Promise<{
|
58
|
+
[key: string]: boolean | string | number;
|
59
|
+
}>;
|
39
60
|
/** Session data population */
|
40
61
|
sessionData?: string | undefined;
|
41
62
|
/** Next-Auth Session Secret */
|
42
63
|
sessionSecret: string;
|
43
64
|
};
|
44
65
|
|
45
|
-
export type AuthTokenRequestErrorCode =
|
46
|
-
| 'IDENTITY_NOT_FOUND'
|
47
|
-
| 'MULTIPLE_IDENTITY_MATCHES';
|
66
|
+
export type AuthTokenRequestErrorCode = 'IDENTITY_NOT_FOUND' | 'MULTIPLE_IDENTITY_MATCHES';
|
48
67
|
|
49
68
|
export type PasswordAuthErrorCode =
|
50
69
|
| AuthTokenRequestErrorCode
|