@opensaas/keystone-nextjs-auth 21.1.1 → 22.2.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 +26 -0
- package/dist/declarations/src/index.d.ts +3 -3
- package/dist/declarations/src/pages/NextAuthPage.d.ts +17 -12
- package/dist/declarations/src/templates/auth.d.ts +2 -4
- package/dist/declarations/src/templates/next-config.d.ts +1 -1
- package/dist/declarations/src/{types.d.ts → types/index.d.ts} +29 -8
- package/dist/opensaas-keystone-nextjs-auth.cjs.dev.js +64 -49
- package/dist/opensaas-keystone-nextjs-auth.cjs.prod.js +63 -48
- package/dist/opensaas-keystone-nextjs-auth.esm.js +64 -49
- package/package.json +2 -4
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.dev.js +49 -38
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.cjs.prod.js +49 -38
- package/pages/NextAuthPage/dist/opensaas-keystone-nextjs-auth-pages-NextAuthPage.esm.js +49 -37
- package/src/gql/getBaseAuthSchema.ts +1 -4
- package/src/index.ts +96 -86
- package/src/lib/findMatchingIdentity.ts +1 -4
- package/src/pages/NextAuthPage.tsx +58 -71
- package/src/schema.ts +2 -4
- package/src/templates/auth.ts +12 -5
- package/src/templates/next-config.ts +1 -5
- package/src/{types.ts → types/index.ts} +28 -11
- package/src/types/next-auth.d.ts +19 -0
@@ -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.');
|
@@ -76,7 +73,6 @@ function NextAuthPage(props) {
|
|
76
73
|
}
|
77
74
|
|
78
75
|
const list = query[listKey];
|
79
|
-
const queryAPI = query[listKey];
|
80
76
|
const protectIdentities = true;
|
81
77
|
return NextAuth({
|
82
78
|
cookies,
|
@@ -106,7 +102,7 @@ function NextAuthPage(props) {
|
|
106
102
|
account,
|
107
103
|
profile
|
108
104
|
}) : {};
|
109
|
-
const result = await validateNextAuth(identityField, identity, protectIdentities,
|
105
|
+
const result = await validateNextAuth(identityField, identity, protectIdentities, list); // ID
|
110
106
|
|
111
107
|
const data = _objectSpread({
|
112
108
|
[identityField]: identity
|
@@ -114,26 +110,38 @@ function NextAuthPage(props) {
|
|
114
110
|
|
115
111
|
if (!result.success) {
|
116
112
|
if (!autoCreate) {
|
117
|
-
console.log('`autoCreate` if set to `false`, skipping user auto-creation');
|
118
113
|
return false;
|
119
114
|
}
|
120
115
|
|
121
|
-
console.log('`autoCreate` if set to `true`, auto-creating a new user');
|
122
116
|
const createUser = await list.createOne({
|
123
117
|
data
|
124
118
|
}).then(returned => {
|
125
|
-
|
126
|
-
|
119
|
+
return {
|
120
|
+
success: true,
|
121
|
+
user: returned
|
122
|
+
};
|
127
123
|
}).catch(error => {
|
128
|
-
console.
|
124
|
+
console.error(error);
|
129
125
|
throw new Error(error);
|
130
126
|
});
|
131
|
-
|
132
|
-
|
133
|
-
} // await list.updateOne({where: {id: result.item.id}, data});
|
134
|
-
|
127
|
+
return createUser.success;
|
128
|
+
}
|
135
129
|
|
136
|
-
|
130
|
+
const updateUser = await list.updateOne({
|
131
|
+
where: {
|
132
|
+
id: result.item.id
|
133
|
+
},
|
134
|
+
data
|
135
|
+
}).then(returned => {
|
136
|
+
return {
|
137
|
+
success: true,
|
138
|
+
user: returned
|
139
|
+
};
|
140
|
+
}).catch(error => {
|
141
|
+
console.error(error);
|
142
|
+
throw new Error(error);
|
143
|
+
});
|
144
|
+
return updateUser.success;
|
137
145
|
},
|
138
146
|
|
139
147
|
async redirect({
|
@@ -146,12 +154,20 @@ function NextAuthPage(props) {
|
|
146
154
|
session,
|
147
155
|
token
|
148
156
|
}) {
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
157
|
+
let returnSession = session;
|
158
|
+
|
159
|
+
if (!token.itemId) {
|
160
|
+
return {
|
161
|
+
expires: '0'
|
162
|
+
};
|
163
|
+
} else {
|
164
|
+
returnSession = _objectSpread(_objectSpread({}, session), {}, {
|
165
|
+
data: token.data,
|
166
|
+
subject: token.sub,
|
167
|
+
listKey: token.listKey,
|
168
|
+
itemId: token.itemId
|
169
|
+
});
|
170
|
+
}
|
155
171
|
|
156
172
|
return returnSession;
|
157
173
|
},
|
@@ -160,26 +176,22 @@ function NextAuthPage(props) {
|
|
160
176
|
token
|
161
177
|
}) {
|
162
178
|
const identity = token.sub;
|
179
|
+
const result = await validateNextAuth(identityField, identity, protectIdentities, list);
|
163
180
|
|
164
|
-
if (!
|
165
|
-
|
166
|
-
|
167
|
-
if (!result.success) {
|
168
|
-
return token;
|
169
|
-
}
|
170
|
-
|
181
|
+
if (!result.success) {
|
182
|
+
token.itemId = null;
|
183
|
+
} else {
|
171
184
|
token.itemId = result.item.id;
|
185
|
+
const data = await query[listKey].findOne({
|
186
|
+
where: {
|
187
|
+
id: token.itemId
|
188
|
+
},
|
189
|
+
query: sessionData || 'id'
|
190
|
+
});
|
191
|
+
token.data = data;
|
172
192
|
}
|
173
193
|
|
174
|
-
const data = await query[listKey].findOne({
|
175
|
-
where: {
|
176
|
-
id: token.itemId
|
177
|
-
},
|
178
|
-
query: sessionData || 'id'
|
179
|
-
});
|
180
|
-
|
181
194
|
const returnToken = _objectSpread(_objectSpread({}, token), {}, {
|
182
|
-
data,
|
183
195
|
subject: token.sub,
|
184
196
|
listKey
|
185
197
|
});
|
@@ -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,26 @@
|
|
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 {
|
17
|
+
import { Session } from 'next-auth';
|
18
|
+
import { nextConfigTemplate } from './templates/next-config';
|
18
19
|
// import * as Path from 'path';
|
19
20
|
|
20
|
-
import { AuthConfig, KeystoneOAuthConfig,
|
21
|
-
import { getSchemaExtension } from
|
22
|
-
import { authTemplate } from
|
21
|
+
import { AuthConfig, KeystoneOAuthConfig, AuthSessionStrategy } from './types';
|
22
|
+
import { getSchemaExtension } from './schema';
|
23
|
+
import { authTemplate } from './templates/auth';
|
23
24
|
|
24
25
|
/**
|
25
26
|
* createAuth function
|
@@ -27,7 +28,7 @@ import { authTemplate } from "./templates/auth";
|
|
27
28
|
* Generates config for Keystone to implement standard auth features.
|
28
29
|
*/
|
29
30
|
|
30
|
-
export type { NextAuthProviders, KeystoneOAuthConfig } from
|
31
|
+
export type { NextAuthProviders, KeystoneOAuthConfig } from './types';
|
31
32
|
export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
32
33
|
autoCreate,
|
33
34
|
cookies,
|
@@ -45,7 +46,7 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
45
46
|
// or whether always being true is what we want, in which case we can refactor our code
|
46
47
|
// to match this. -TL
|
47
48
|
|
48
|
-
const customPath = !keystonePath || keystonePath ===
|
49
|
+
const customPath = !keystonePath || keystonePath === '/' ? '' : keystonePath;
|
49
50
|
/**
|
50
51
|
* pageMiddleware
|
51
52
|
*
|
@@ -56,36 +57,41 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
56
57
|
* - to the init page when initFirstItem is configured, and there are no user in the database
|
57
58
|
* - to the signin page when no valid session is present
|
58
59
|
*/
|
59
|
-
const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>[
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
const pageMiddleware: AdminUIConfig<BaseKeystoneTypeInfo>['pageMiddleware'] = async ({
|
61
|
+
context,
|
62
|
+
isValidSession,
|
63
|
+
}) => {
|
64
|
+
const { req, session } = context;
|
65
|
+
const pathname = url.parse(req?.url!).pathname!;
|
63
66
|
|
64
|
-
|
65
|
-
if (pathname === `${customPath}/api/auth/signin`) {
|
66
|
-
return { kind: "redirect", to: `${customPath}` };
|
67
|
-
}
|
68
|
-
if (customPath !== "" && pathname === "/") {
|
69
|
-
return { kind: "redirect", to: `${customPath}` };
|
70
|
-
}
|
71
|
-
return;
|
72
|
-
}
|
67
|
+
if (isValidSession) {
|
73
68
|
if (
|
74
|
-
pathname
|
75
|
-
pathname.includes(
|
76
|
-
pathname.includes(pages?.signIn) ||
|
77
|
-
pathname.includes(pages?.error) ||
|
78
|
-
pathname.includes(pages?.signOut)
|
69
|
+
pathname === `${customPath}/api/auth/signin` ||
|
70
|
+
(pages?.signIn && pathname.includes(pages?.signIn))
|
79
71
|
) {
|
80
|
-
return;
|
72
|
+
return { kind: 'redirect', to: `${customPath}` };
|
81
73
|
}
|
82
|
-
if (
|
83
|
-
return {
|
84
|
-
kind: "redirect",
|
85
|
-
to: pages?.signIn || `${customPath}/api/auth/signin`,
|
86
|
-
};
|
74
|
+
if (customPath !== '' && pathname === '/') {
|
75
|
+
return { kind: 'redirect', to: `${customPath}` };
|
87
76
|
}
|
88
|
-
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
if (
|
80
|
+
pathname.includes('/_next/') ||
|
81
|
+
pathname.includes('/api/auth/') ||
|
82
|
+
(pages?.signIn && pathname.includes(pages?.signIn)) ||
|
83
|
+
(pages?.error && pathname.includes(pages?.error)) ||
|
84
|
+
(pages?.signOut && pathname.includes(pages?.signOut))
|
85
|
+
) {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
if (!session && !pathname.includes(`${customPath}/api/auth/`)) {
|
89
|
+
return {
|
90
|
+
kind: 'redirect',
|
91
|
+
to: pages?.signIn || `${customPath}/api/auth/signin`,
|
92
|
+
};
|
93
|
+
}
|
94
|
+
};
|
89
95
|
|
90
96
|
/**
|
91
97
|
* getAdditionalFiles
|
@@ -98,8 +104,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
98
104
|
const getAdditionalFiles = () => {
|
99
105
|
const filesToWrite: AdminFileToWrite[] = [
|
100
106
|
{
|
101
|
-
mode:
|
102
|
-
outputPath:
|
107
|
+
mode: 'write',
|
108
|
+
outputPath: 'pages/api/auth/[...nextauth].js',
|
103
109
|
src: authTemplate({
|
104
110
|
autoCreate,
|
105
111
|
identityField,
|
@@ -109,8 +115,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
109
115
|
}),
|
110
116
|
},
|
111
117
|
{
|
112
|
-
mode:
|
113
|
-
outputPath:
|
118
|
+
mode: 'write',
|
119
|
+
outputPath: 'next.config.js',
|
114
120
|
src: nextConfigTemplate({ keystonePath: customPath }),
|
115
121
|
},
|
116
122
|
];
|
@@ -186,52 +192,61 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
186
192
|
- [ ] We could support additional where input to validate item sessions (e.g an isEnabled boolean)
|
187
193
|
*/
|
188
194
|
const withItemData = (
|
189
|
-
_sessionStrategy:
|
190
|
-
):
|
191
|
-
const { get,
|
195
|
+
_sessionStrategy: AuthSessionStrategy<Record<string, any>>
|
196
|
+
): AuthSessionStrategy<{ listKey: string; itemId: string; data: any }> => {
|
197
|
+
const { get, end, ...sessionStrategy } = _sessionStrategy;
|
192
198
|
return {
|
193
199
|
...sessionStrategy,
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
const session = await start({ res });
|
198
|
-
return session;
|
199
|
-
},
|
200
|
-
get: async ({ req }) => {
|
200
|
+
get: async ({ req, createContext }) => {
|
201
|
+
const session = await get({ req, createContext });
|
202
|
+
const sudoContext = createContext({ sudo: true });
|
201
203
|
const pathname = url.parse(req?.url!).pathname!;
|
202
|
-
|
204
|
+
let nextSession: Session;
|
205
|
+
if (pathname.includes('/api/auth')) {
|
203
206
|
return;
|
204
207
|
}
|
205
|
-
if (req.headers
|
206
|
-
|
208
|
+
if (req.headers?.authorization?.split(' ')[0] === 'Bearer') {
|
209
|
+
nextSession = (await getToken({
|
207
210
|
req,
|
208
211
|
secret: sessionSecret,
|
209
|
-
})) as
|
210
|
-
|
211
|
-
|
212
|
-
return token;
|
213
|
-
}
|
212
|
+
})) as Session;
|
213
|
+
} else {
|
214
|
+
nextSession = (await getSession({ req })) as Session;
|
214
215
|
}
|
215
|
-
const nextSession: unknown = await getSession({ req });
|
216
216
|
|
217
|
-
if (
|
218
|
-
|
217
|
+
if (
|
218
|
+
!nextSession ||
|
219
|
+
!nextSession.listKey ||
|
220
|
+
nextSession.listKey !== listKey ||
|
221
|
+
!nextSession.itemId ||
|
222
|
+
!sudoContext.query[listKey] ||
|
223
|
+
!nextSession.itemId
|
224
|
+
) {
|
225
|
+
return;
|
219
226
|
}
|
227
|
+
return {
|
228
|
+
...nextSession,
|
229
|
+
data: nextSession.data,
|
230
|
+
listKey: nextSession.listKey,
|
231
|
+
itemId: nextSession.itemId,
|
232
|
+
...session,
|
233
|
+
};
|
220
234
|
},
|
221
|
-
end: async ({ res, req }) => {
|
235
|
+
end: async ({ res, req, createContext }) => {
|
236
|
+
await end({ res, req, createContext });
|
222
237
|
const TOKEN_NAME =
|
223
|
-
process.env.NODE_ENV ===
|
224
|
-
?
|
225
|
-
:
|
238
|
+
process.env.NODE_ENV === 'production'
|
239
|
+
? '__Secure-next-auth.session-token'
|
240
|
+
: 'next-auth.session-token';
|
226
241
|
res.setHeader(
|
227
|
-
|
228
|
-
cookie.serialize(TOKEN_NAME,
|
242
|
+
'Set-Cookie',
|
243
|
+
cookie.serialize(TOKEN_NAME, '', {
|
229
244
|
maxAge: 0,
|
230
245
|
expires: new Date(),
|
231
246
|
httpOnly: true,
|
232
|
-
secure: process.env.NODE_ENV ===
|
233
|
-
path:
|
234
|
-
sameSite:
|
247
|
+
secure: process.env.NODE_ENV === 'production',
|
248
|
+
path: '/',
|
249
|
+
sameSite: 'lax',
|
235
250
|
// TODO: Update parse to URL
|
236
251
|
domain: url.parse(req.url as string).hostname as string,
|
237
252
|
})
|
@@ -257,28 +272,24 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
257
272
|
ui = {
|
258
273
|
...keystoneConfig.ui,
|
259
274
|
publicPages: [...(keystoneConfig.ui.publicPages || []), ...publicPages],
|
260
|
-
getAdditionalFiles: [
|
261
|
-
|
262
|
-
|
263
|
-
],
|
264
|
-
pageMiddleware: async (args) =>
|
265
|
-
(await pageMiddleware(args)) ??
|
266
|
-
keystoneConfig?.ui?.pageMiddleware?.(args),
|
275
|
+
getAdditionalFiles: [...(keystoneConfig.ui?.getAdditionalFiles || []), getAdditionalFiles],
|
276
|
+
pageMiddleware: async args =>
|
277
|
+
(await pageMiddleware(args)) ?? keystoneConfig?.ui?.pageMiddleware?.(args),
|
267
278
|
enableSessionItem: true,
|
268
279
|
isAccessAllowed: async (context: KeystoneContext) => {
|
269
280
|
const { req } = context;
|
270
281
|
const pathname = url.parse(req?.url!).pathname!;
|
271
282
|
|
272
283
|
// Allow nextjs scripts and static files to be accessed without auth
|
273
|
-
if (pathname.includes(
|
284
|
+
if (pathname.includes('/_next/')) {
|
274
285
|
return true;
|
275
286
|
}
|
276
287
|
|
277
288
|
// Allow keystone to access /api/__keystone_api_build for hot reloading
|
278
289
|
if (
|
279
|
-
process.env.NODE_ENV !==
|
290
|
+
process.env.NODE_ENV !== 'production' &&
|
280
291
|
context.req?.url !== undefined &&
|
281
|
-
new URL(context.req.url,
|
292
|
+
new URL(context.req.url, 'http://example.com').pathname ===
|
282
293
|
`${customPath}/api/__keystone_api_build`
|
283
294
|
) {
|
284
295
|
return true;
|
@@ -291,9 +302,8 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
291
302
|
};
|
292
303
|
}
|
293
304
|
|
294
|
-
if (!keystoneConfig.session)
|
295
|
-
|
296
|
-
const session = withItemData(keystoneConfig.session);
|
305
|
+
if (!keystoneConfig.session) throw new TypeError('Missing .session configuration');
|
306
|
+
const session = withItemData(keystoneConfig.session) as SessionStrategy<any>;
|
297
307
|
|
298
308
|
const existingExtendGraphQLSchema = keystoneConfig.extendGraphqlSchema;
|
299
309
|
return {
|
@@ -312,7 +322,7 @@ export function createAuth<GeneratedListTypes extends BaseListTypeInfo>({
|
|
312
322
|
generateNodeAPI: true,
|
313
323
|
},
|
314
324
|
extendGraphqlSchema: existingExtendGraphQLSchema
|
315
|
-
?
|
325
|
+
? schema => existingExtendGraphQLSchema(extendGraphqlSchema(schema))
|
316
326
|
: extendGraphqlSchema,
|
317
327
|
};
|
318
328
|
};
|
@@ -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,34 +1,31 @@
|
|
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
|
-
|
12
|
-
type CoreNextAuthPageProps = {
|
7
|
+
export type NextAuthTemplateProps = {
|
13
8
|
autoCreate: boolean;
|
14
|
-
cookies?: Partial<CookiesOptions>;
|
15
|
-
events?: Partial<EventCallbacks>;
|
16
9
|
identityField: string;
|
17
|
-
jwt?: Partial<JWTOptions>;
|
18
10
|
listKey: string;
|
19
|
-
pages?: Partial<PagesOptions>;
|
20
|
-
providers?: Provider[];
|
21
|
-
resolver?: Function | undefined;
|
22
11
|
sessionData: string | undefined;
|
23
12
|
sessionSecret: string;
|
24
13
|
};
|
25
14
|
|
26
|
-
type
|
27
|
-
|
28
|
-
|
29
|
-
|
15
|
+
export type CoreNextAuthPageProps = {
|
16
|
+
cookies?: Partial<CookiesOptions>;
|
17
|
+
events?: Partial<EventCallbacks>;
|
18
|
+
jwt?: Partial<JWTOptions>;
|
19
|
+
pages?: Partial<PagesOptions>;
|
20
|
+
providers: Provider[];
|
21
|
+
resolver?: (args: { user: any; profile: any; account: any }) => Promise<{
|
22
|
+
[key: string]: boolean | string | number;
|
23
|
+
}>;
|
24
|
+
} & NextAuthTemplateProps;
|
30
25
|
|
31
|
-
export type NextAuthPageProps = CoreNextAuthPageProps &
|
26
|
+
export type NextAuthPageProps = CoreNextAuthPageProps & {
|
27
|
+
query: KeystoneListsAPI<any>;
|
28
|
+
};
|
32
29
|
|
33
30
|
export default function NextAuthPage(props: NextAuthPageProps) {
|
34
31
|
const {
|
@@ -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.');
|
@@ -59,7 +54,6 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
59
54
|
}
|
60
55
|
|
61
56
|
const list = query[listKey];
|
62
|
-
const queryAPI = query[listKey];
|
63
57
|
const protectIdentities = true;
|
64
58
|
|
65
59
|
return NextAuth({
|
@@ -79,16 +73,9 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
79
73
|
} else {
|
80
74
|
identity = 0;
|
81
75
|
}
|
82
|
-
const userInput = resolver
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
const result = await validateNextAuth(
|
87
|
-
identityField,
|
88
|
-
identity,
|
89
|
-
protectIdentities,
|
90
|
-
queryAPI
|
91
|
-
);
|
76
|
+
const userInput = resolver ? await resolver({ user, account, profile }) : {};
|
77
|
+
|
78
|
+
const result = await validateNextAuth(identityField, identity, protectIdentities, list);
|
92
79
|
// ID
|
93
80
|
const data: any = {
|
94
81
|
[identityField]: identity,
|
@@ -97,66 +84,67 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
97
84
|
|
98
85
|
if (!result.success) {
|
99
86
|
if (!autoCreate) {
|
100
|
-
console.log(
|
101
|
-
'`autoCreate` if set to `false`, skipping user auto-creation'
|
102
|
-
);
|
103
87
|
return false;
|
104
88
|
}
|
105
|
-
console.log(
|
106
|
-
'`autoCreate` if set to `true`, auto-creating a new user'
|
107
|
-
);
|
108
89
|
|
109
90
|
const createUser = await list
|
110
91
|
.createOne({ data })
|
111
|
-
.then(
|
112
|
-
|
113
|
-
return true;
|
92
|
+
.then(returned => {
|
93
|
+
return { success: true, user: returned };
|
114
94
|
})
|
115
|
-
.catch(
|
116
|
-
console.
|
95
|
+
.catch(error => {
|
96
|
+
console.error(error);
|
117
97
|
throw new Error(error);
|
118
98
|
});
|
119
|
-
|
120
|
-
return createUser;
|
99
|
+
return createUser.success;
|
121
100
|
}
|
122
|
-
|
123
|
-
|
101
|
+
|
102
|
+
const updateUser = await list
|
103
|
+
.updateOne({ where: { id: result.item.id }, data })
|
104
|
+
.then(returned => {
|
105
|
+
return { success: true, user: returned };
|
106
|
+
})
|
107
|
+
.catch(error => {
|
108
|
+
console.error(error);
|
109
|
+
throw new Error(error);
|
110
|
+
});
|
111
|
+
return updateUser.success;
|
124
112
|
},
|
125
113
|
async redirect({ url }) {
|
126
114
|
return url;
|
127
115
|
},
|
128
116
|
async session({ session, token }) {
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
117
|
+
let returnSession = session;
|
118
|
+
if (!token.itemId) {
|
119
|
+
return { expires: '0' };
|
120
|
+
} else {
|
121
|
+
returnSession = {
|
122
|
+
...session,
|
123
|
+
data: token.data,
|
124
|
+
subject: token.sub,
|
125
|
+
listKey: token.listKey as string,
|
126
|
+
itemId: token.itemId as string,
|
127
|
+
};
|
128
|
+
}
|
129
|
+
|
136
130
|
return returnSession;
|
137
131
|
},
|
138
132
|
async jwt({ token }) {
|
139
133
|
const identity = token.sub as number | string;
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
queryAPI
|
146
|
-
);
|
147
|
-
|
148
|
-
if (!result.success) {
|
149
|
-
return token;
|
150
|
-
}
|
134
|
+
const result = await validateNextAuth(identityField, identity, protectIdentities, list);
|
135
|
+
|
136
|
+
if (!result.success) {
|
137
|
+
token.itemId = null;
|
138
|
+
} else {
|
151
139
|
token.itemId = result.item.id;
|
140
|
+
const data = await query[listKey].findOne({
|
141
|
+
where: { id: token.itemId },
|
142
|
+
query: sessionData || 'id',
|
143
|
+
});
|
144
|
+
token.data = data;
|
152
145
|
}
|
153
|
-
const data = await query[listKey].findOne({
|
154
|
-
where: { id: token.itemId },
|
155
|
-
query: sessionData || 'id',
|
156
|
-
});
|
157
146
|
const returnToken = {
|
158
147
|
...token,
|
159
|
-
data,
|
160
148
|
subject: token.sub,
|
161
149
|
listKey,
|
162
150
|
};
|
@@ -167,5 +155,4 @@ export default function NextAuthPage(props: NextAuthPageProps) {
|
|
167
155
|
});
|
168
156
|
}
|
169
157
|
|
170
|
-
export const getNextAuthPage = (props: NextAuthPageProps) => () =>
|
171
|
-
NextAuthPage({ ...props });
|
158
|
+
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
|
});
|