opensaasau / keystone-nextjs-auth Goto Github PK
View Code? Open in Web Editor NEWA package that add social auth to Keystone-6 (https://keystonejs.com/) by using next-authjs (https://next-auth.js.org/)
License: MIT License
A package that add social auth to Keystone-6 (https://keystonejs.com/) by using next-authjs (https://next-auth.js.org/)
License: MIT License
For some reason I just can't get the Google provider to work. I was able to debug some (as per the two PRs I sent) but I'm kinda stumped now, I think I just don't have enough knowledge of nextjs-auth or keystone to debug it properly.
Basically I can get it to pop up the google auth screen, I can choose my google account but when it lands on the callback page /api/auth/callback/google?state=....
I'm redirected to an error page /api/auth/error?error=AccessDenied
.
I installed keystone-next at version 22 and couldn't get it working. I tried updating latest keystone (23.0.2 as of writing) and am getting a typescript error now when using withAuth
by the way.
I used the setup where keystone generates a User list and a Post list, and installed using a normal email/password setup. I tried to add this package afterward. That setup did not have a subjectId
field, so I have since added that, but hasn't seemed to help.
This is my keystone.ts file, maybe I'm doing something wrong with my config?
import { config } from '@keystone-next/keystone/schema'
import { statelessSessions } from '@keystone-next/keystone/session'
// original keystone auth
// import { createAuth } from '@keystone-next/auth'
import { lists } from './schema'
import {
createAuth,
nextAuthProviders as Providers,
} from '@opensaas/keystone-nextjs-auth'
let sessionSecret = process.env.SESSION_SECRET
if (!sessionSecret) {
if (process.env.NODE_ENV === 'production') {
throw new Error(
'The SESSION_SECRET environment variable must be set in production'
)
} else {
sessionSecret =
'-- DEV SECRET - The bodies are buried under the binary tree --'
}
}
let sessionMaxAge = 60 * 60 * 24 * 30 // 30 days
export const providers = [
Providers.Google({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET
}),
]
const auth = createAuth({
listKey: 'User',
identityField: 'subjectId',
sessionData: `id name email`,
autoCreate: false,
userMap: { subjectId: 'id', name: 'name' },
accountMap: {},
profileMap: { email: 'email' },
})
// Original keystone auth config
// const { withAuth } = createAuth({
// listKey: 'User',
// identityField: 'email',
// secretField: 'password',
// sessionData: 'name',
// initFirstItem: {
// fields: ['name', 'email', 'password'],
// },
// })
const session = statelessSessions({
maxAge: sessionMaxAge,
secret: sessionSecret,
})
const getDbUrl = () => {
if (
process.env.DATABASE_URL &&
typeof process.env.DATABASE_URL === 'string' &&
process.env.DATABASE_URL !== 'undefined' // for some reason this can end up as a string of 'undefined'
) {
return process.env.DATABASE_URL
}
if (
process.env.DB_NAME &&
process.env.DB_PASS &&
process.env.DB_USER &&
process.env.DB_HOST
) {
return `postgres://${process.env.DB_USER}:${process.env.DB_PASS}@${process.env.DB_HOST}/${process.env.DB_NAME}`
}
// local dev default
return 'postgres://postgres:[email protected]/example'
}
export default auth.withAuth(
config({
experimental: {
generateNodeAPI: true,
},
db: {
adapter: 'prisma_postgresql',
url: getDbUrl(),
},
lists,
session,
})
)
Any ideas on where I should be looking to start debugging?
Next-authjs providers that have multiple words like AzureADB2C
have a url that uses -
between words no just toLower()
of the name.
So I'm using this in my Keystone app and my end goal is to replace the default dashboard with a much more complete dashboard with overviews across many sources.
I need to be able to get the currently signed in user to be able to show relevant and scoped information - such as bits they can access depending on their role.
I am using latest version of keystone and keystone-nextjs-auth package and when I click on sign in button the page refreshes and nothing else happens:
Keystone Package versions
"@graphql-tools/schema": "^9.0.17",
"@keystone-6/auth": "^7.0.0",
"@keystone-6/core": "^5.1.0",
"@keystone-6/fields-document": "^7.0.0",
"@keystone-ui/core": "^5.0.2",
This is what I get in terminal
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error undefined {
error: {},
url: 'http://localhost:3000/admin/api/auth/session',
message: undefined
}
here is my .env content
NEXTAUTH_URL=http://localhost:3000/admin/api/auth
SESSION_SECRET="H0Rvwx5gy5elNS2VhUuQfo5+5sL9WWJQ8dbIR/YsMs0="
DATABASE_URL=postgres://test:test@localhost:5432/test
Any ideas? any help is appreciated.
async <2.6.4
Severity: high
Prototype Pollution in async - GHSA-fwr7-v2mv-hh25
No fix available
node_modules/jake/node_modules/async
jake >=8.0.1
Depends on vulnerable versions of async
node_modules/jake
ejs >=3.1.2
Depends on vulnerable versions of jake
node_modules/ejs
@opensaas/keystone-nextjs-auth *
Depends on vulnerable versions of ejs
node_modules/@opensaas/keystone-nextjs-auth
4 high severity vulnerabilities
Hi, I've just begun to use your package and added a github authentication provider but, whenever I complete the authentication flow I get this error.
http://localhost:3000/admin/api/auth/error?error=Variable%20%22%24where%22%20got%20invalid%20value%2032213671%20at%20%22where.subjectId.equals%22%3B%20String%20cannot%20represent%20a%20non%20string%20value%3A%2032213671
I'm running the latest version of this package (14.1.1) and version 26.1.0 of @keystone-next/keystone
Link to Github user API reference:
https://docs.github.com/en/rest/reference/users
Hello,
I am trying to make Google Auth work with my Keystone Project.
I got to the point where user is created on sign in, but every time I sign in an attempt is made to create the user again. It leads to an error and I don't have a session.
After some digging in the code, I found out the following is happening :
signIn()
callback in NextAuthPage, we check if the user already exist using validateNextAuth
. We give it the identityField
, but the identity
we use to fetch the user is the value of user.id
. So in the end findMatchingIdentity()
makes a bad query, asking for a user whose email adress is its provider ID so it fails.identityField
provided by the user. This time data is well formatted so it's a duplicate : rejected.async signIn({ user, account, profile }) {
let identity;
if (typeof user.id === 'string') {
identity = user.id;
} else if (typeof user.id === 'number') {
identity = user.id;
} else {
identity = 0;
}
const userInput = resolver ? await resolver({ user, account, profile }) : {};
const result = await validateNextAuth(identityField, identity, protectIdentities, list);
// ID
const data: any = {
[identityField]: identity,
...userInput,
};
if (!result.success) {
if (!autoCreate) {
return false;
}
const createUser = await list
.createOne({ data })
.then(returned => {
return { success: true, user: returned };
})
.catch(error => {
console.error(error);
throw new Error(error);
});
return createUser.success;
}
const updateUser = await list
.updateOne({ where: { id: result.item.id }, data })
.then(returned => {
return { success: true, user: returned };
})
.catch(error => {
console.error(error);
throw new Error(error);
});
return updateUser.success;
}
So I'm not sure of the actions to take on my side :
id
field from the provider user to my database ?providerIdentityField
to match with our DB identityField
?user
a standard property from OAuth protocol, identical for every provider ?In my use case using the email
field from my user List as the identity field feels appropriate so I'd like to stick with it instead of storing google IDs.
I'm having an issue running the keystone-nextjs-auth backend locally with an error on inputPaths for custom pages.
I don't see much information on the keystone js docs for getAdditionalFiles ui property, but that seems to be the issue.
After running yarn dev:backend
, i'm left with this error:
🚨 There was an error loading your Keystone config
Error: An inputPath of "../../customPages/signin.js" was provided to copy but inputPaths must be absolute
at writeAdminFile (/Users/salo/Code/examples/keystone-nextjs-auth/node_modules/@keystone-6/core/dist/initConfig-c6b5cfcb.cjs.dev.js:557:13)
at /Users/salo/Code/examples/keystone-nextjs-auth/node_modules/@keystone-6/core/dist/initConfig-c6b5cfcb.cjs.dev.js:604:69
at Array.map (<anonymous>)
at Object.generateAdminUI (/Users/salo/Code/examples/keystone-nextjs-auth/node_modules/@keystone-6/core/dist/initConfig-c6b5cfcb.cjs.dev.js:604:57)
at initKeystone (/Users/salo/Code/examples/keystone-nextjs-auth/node_modules/@keystone-6/core/scripts/dist/keystone-6-core-scripts.cjs.dev.js:265:11)
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
error: {
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
' at /Users/salo/Code/examples/keystone-nextjs-auth/node_modules/next/dist/compiled/node-fetch/index.js:1:49606\n' +
' at runMicrotasks (<anonymous>)\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)',
name: 'FetchError'
},
url: 'http://localhost:3000/api/auth/session',
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
}
it seems to complain about the relative path on inputPath
in keystone.ts:
ui: {
isAccessAllowed: (context: KeystoneContext) => !!context.session?.data,
publicPages: ['/admin/auth/signin', '/admin/auth/error'],
getAdditionalFiles: [
async () => [
{
mode: 'copy',
inputPath: Path.join(__dirname, './customPages/signin.js'),
outputPath: 'pages/auth/signin.js',
},
{
mode: 'copy',
inputPath: Path.join(__dirname, './customPages/error.js'),
outputPath: 'pages/auth/error.js',
},
],
],
},
I tried several changes to that path (and tried using write
instead of copy with putting the src directly in keystone.ts), but still not getting it to run.
Any ideas on how to fix that?
Thanks!
Hi, I tried to build the example front end app using its docker file, but I got the following errors:
executor failed running [/bin/sh -c yarn build]: exit code: 1
ERROR: Service 'ks-frontend-demo' failed to build : Build failed`
So i edited apps/ks-frontend-demo/next.config.js to disable linting during builds, and the error went away.
npm i --save-dev @types/lodash
if it exists or add a new declaration (.d.ts) file containing declare module 'lodash/isEqual';
So I added a RUN yarn add -D @types/lodash
before yarn install in the docker file, and it worked.
But now..
./pages/index.tsx:42:14
Type error: Property 'itemId' does not exist on type 'Session'.
40 | )}
41 | {!user && <p>No User</p>}
> 42 | {data?.itemId ? (
| ^
43 | <>
44 | <p>Your email stored in your NextAuthjs Session as: "{data?.user?.email}"</p>
45 | <Button
> Build error occurred
Am I doing something wrong?
Thanks in advance
Hey Team,
A few days ago the Keystone team removed the experimental feature generateNodeAPI
.
Since this package requires generateNodeAPI
, what's the best next steps to supporting this breaking change?
PR removing the feature: keystonejs/keystone#7957
Definitely open to assist in any way I can.
Hi, I tried to use CredentialsProvider but keep getting access denied when logging in. I then realised that /api/auth/callback/credentials is not supported (I get this error when i visit the url Error: Callback for provider type credentials not supported
). Thanks
Edit: I tried with google provider and it still doesn't work. It seems to be an issue with the isAccessAllowed function internally in this package. The context.session
is undefined even if i am logged in
I am about 80% through getting an Azure Active Directory user to log in after working through #238 🙂
http://localhost:3000
http://localhost:3000/admin/api/auth/signin
At this point I am redirected back to http://localhost:3000/admin/api/auth/signin
with the sign in button visible. I can't go anywhere without being redirected back to this page again. I can't see any errors or 404s in the browser inspector.
I am still receiving the following message in the console, though not sure if this is what is causing the issue:
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
error: {
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
' at /home/enablenz/projects/enzweb/api/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)',
name: 'FetchError'
},
url: 'http://localhost:3000/api/auth/session',
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
}
These are my files.
keystone.ts
import * as dotenv from 'dotenv';
dotenv.config();
import { config } from '@keystone-6/core';
import { KeystoneContext } from '@keystone-6/core/types';
import { lists } from './schema';
import { withAuth, session } from './auth';
export default withAuth(
config({
db: {
provider: 'mysql',
url: process.env.DATABASE_URL,
useMigrations: true,
idField: { kind: 'uuid' },
enableLogging: true,
},
ui: {
isAccessAllowed: (context: KeystoneContext) => !!context.session,
},
lists,
session,
})
);
auth.ts
import { randomBytes } from 'crypto';
import { createAuth } from '@opensaas/keystone-nextjs-auth';
import AzureADProvider from "@opensaas/keystone-nextjs-auth/providers/azure-ad";
import { statelessSessions } from '@keystone-6/core/session';
let sessionSecret = process.env.SESSION_SECRET;
if (!sessionSecret && process.env.NODE_ENV !== 'production') {
sessionSecret = randomBytes(32).toString('hex');
}
const { withAuth } = createAuth({
listKey: 'User',
identityField: 'subjectId',
sessionData: `id name email`,
sessionSecret: sessionSecret,
autoCreate: true,
resolver: async ({user, profile, account}) => {
console.log(user);
console.log(profile);
console.log(account);
const name = user.name as string;
const email = user.email as string;
return { email, name };
},
keystonePath: '/admin',
providers: [
AzureADProvider({
clientId: process.env.AZURE_AD_CLIENT_ID,
clientSecret: process.env.AZURE_AD_CLIENT_SECRET,
tenantId: process.env.AZURE_AD_TENANT_ID,
}),
]
});
const sessionMaxAge = 60 * 60 * 24 * 30;
// you can find out more at https://keystonejs.com/docs/apis/session#session-api
const session = statelessSessions({
maxAge: sessionMaxAge,
secret: sessionSecret!,
});
export { withAuth, session };
This is how the user table is set up in schema.ts:
User: list({
access: allowAll,
fields: {
name: text({ validation: { isRequired: true } }),
email: text({
validation: { isRequired: true },
isIndexed: 'unique',
}),
subjectId: text({ isIndexed: 'unique' }),
createdAt: timestamp({
defaultValue: { kind: 'now' },
}),
},
}),
And finally, these are the env vars I have set:
AZURE_AD_CLIENT_ID=<secret squirrel>
AZURE_AD_CLIENT_SECRET=<secret squirrel>
AZURE_AD_TENANT_ID=<secret squirrel>
DATABASE_URL=<secret squirrel>
NEXTAUTH_URL=http://localhost:3000/admin/api/auth
NODE_ENV=development
SESSION_SECRET=<secret squirrel>
Is there anything I am missing? Thanks for your patience 👍
Both in my own application and in the example application, im getting this error. When I run yarn keystone dev
it just goes into an infinite loop of compiling and erroring out.
For all I know im doing something wrong, but I follow the documentation here and I also checked next-auth's documentation and I have googled this issue and found somewhat related issues, but I think its a pretty general error since its just the fetch api not being able to read an expected json output.
Since the unexpected character is <
I assumed the response it was getting was html and when I tried to go, to the page it was trying to get to, it seemed like it was returning an html page saying that I didn't have access to this page. But adding the path to the public pages config did nothing.
Here is my main file, its basically the example project but I changed the database to sqlite because it was easier to run locally that way.
import 'dotenv/config';
import * as Path from 'path';
import { config } from '@keystone-6/core';
import { statelessSessions } from '@keystone-6/core/session';
import Auth0 from '@opensaas/keystone-nextjs-auth/providers/auth0';
import { createAuth } from '@opensaas/keystone-nextjs-auth';
import { KeystoneContext } from '@keystone-6/core/types';
import { lists } from './schemas';
let sessionSecret = process.env.SESSION_SECRET;
if (!sessionSecret) {
if (process.env.NODE_ENV === 'production') {
throw new Error('The SESSION_SECRET environment variable must be set in production');
} else {
sessionSecret = '-- DEV COOKIE SECRET; CHANGE ME --';
}
}
const sessionMaxAge = 60 * 60 * 24 * 30; // 30 days
const auth = createAuth({
listKey: 'User',
identityField: 'subjectId',
sessionData: `id name email`,
autoCreate: true,
resolver: async ({ user, profile }: { user: any; profile: any }) => {
const name = user.name as string;
const email = profile.email as string;
return { email, name };
},
pages: {
signIn: '/admin/auth/signin',
},
keystonePath: '/admin',
sessionSecret,
providers: [
Auth0({
clientId: process.env.AUTH0_CLIENT_ID || 'Auth0ClientID',
clientSecret: process.env.AUTH0_CLIENT_SECRET || 'Auth0ClientSecret',
issuer: process.env.AUTH0_ISSUER_BASE_URL || 'https://opensaas.au.auth0.com',
}),
],
});
export default auth.withAuth(
config({
server: {
cors: {
origin: [process.env.FRONTEND || 'http://localhost:7777'],
credentials: true,
},
},
db: {
provider: 'sqlite',
url: 'file:./keystone.db',
},
ui: {
isAccessAllowed: (context: KeystoneContext) => !!context.session?.data,
publicPages: ['/admin/auth/signin', '/admin/auth/error'],
getAdditionalFiles: [
async () => [
{
mode: 'copy',
inputPath: Path.resolve('./customPages/signin.js'),
outputPath: 'pages/auth/signin.js',
},
{
mode: 'copy',
inputPath: Path.resolve('./customPages/error.js'),
outputPath: 'pages/auth/error.js',
},
],
],
},
lists,
session: statelessSessions({
maxAge: sessionMaxAge,
secret: sessionSecret,
}),
experimental: {
generateNodeAPI: true,
},
})
);
Here is what the whole error log looks like
➜ yarn keystone dev
yarn run v1.22.19
$ /Users/eric/Development/web/keystonejs-auth-test/node_modules/.bin/keystone dev
✨ Starting Keystone
⭐️ Dev Server Starting on http://localhost:3000
⭐️ GraphQL API Starting on http://localhost:3000/api/graphql
✨ Generating GraphQL and Prisma schemas
✨ The database is already in sync with the Prisma schema.
✨ Connecting to the database
✨ Creating server
✅ GraphQL API ready
✨ Generating Admin UI code
✨ Preparing Admin UI app
event - compiled client and server successfully in 7.4s (1263 modules)
✅ Admin UI ready
wait - compiling /no-access (client and server)...
event - compiled client and server successfully in 492 ms (1268 modules)
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
error: {
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
' at /Users/eric/Development/web/keystonejs-auth-test/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)',
name: 'FetchError'
},
url: 'http://localhost:3000/api/auth/session',
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
}
wait - compiling /api/__keystone_api_build (client and server)...
event - compiled successfully in 129 ms (159 modules)
wait - compiling...
event - compiled client and server successfully in 174 ms (1290 modules)
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
error: {
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
' at /Users/eric/Development/web/keystonejs-auth-test/node_modules/next/dist/compiled/node-fetch/index.js:1:51220\n' +
' at runMicrotasks (<anonymous>)\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)',
name: 'FetchError'
},
url: 'http://localhost:3000/api/auth/session',
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
}
In @keystone-6/core 5.3.2 "./___internal-do-not-use-will-break-in-patch/admin-ui/next-config" was removed and replaced by content generated from packages/core/src/admin-ui/templates/next-config.ts.
In @opensaas/keystone-nextjs-auth/src/templates/next-config.ts is :
const keystoneConfig = require('@keystone-6/core/___internal-do-not-use-will-break-in-patch/admin-ui/next-config').config;
It takes precedence over keystone.ts config and produce following error :
- error Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error
Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './___internal-do-not-use-will-break-in-patch/admin-ui/next-config' is not defined by "exports" in /cms/node_modules/@keystone-6/core/package.json
at new NodeError (node:internal/errors:399:5)
at exportsNotFound (node:internal/modules/esm/resolve:361:10)
at packageExportsResolve (node:internal/modules/esm/resolve:697:9)
at resolveExports (node:internal/modules/cjs/loader:567:36)
at Module._findPath (node:internal/modules/cjs/loader:636:31)
at Module._resolveFilename (node:internal/modules/cjs/loader:1063:27)
at /cms/node_modules/@keystone-6/core/node_modules/next/dist/server/require-hook.js:189:36
at Module._load (node:internal/modules/cjs/loader:922:27)
at Module.require (node:internal/modules/cjs/loader:1143:19)
at require (node:internal/modules/cjs/helpers:110:18) {
code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}
Should we import the template from Keystone ?
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates are pending. To force PRs open, click the checkbox below.
These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@apollo/client
, @babel/core
, @babel/preset-typescript
, @babel/runtime
, @babel/runtime-corejs3
, @changesets/cli
, @keystone-6/fields-document
, @next/bundle-analyzer
, @next/eslint-plugin-next
, @preconstruct/cli
, @types/ejs
, @types/node
, @types/nprogress
, @types/react
, @types/styled-components
, cross-fetch
, eslint-config-next
, eslint-plugin-jest
, next
, next-auth
, prettier
, react-bootstrap
, styled-components
)@babel/core
, @babel/eslint-parser
, @babel/plugin-transform-runtime
, @babel/plugin-transform-typescript
, @babel/preset-env
, @babel/preset-flow
, @babel/preset-react
, @babel/preset-typescript
, @babel/runtime
, @babel/runtime-corejs3
)@next/bundle-analyzer
, @next/eslint-plugin-next
, eslint-config-next
, next
)@typescript-eslint/eslint-plugin
, @typescript-eslint/parser
)babel-jest
, jest
)@typescript-eslint/eslint-plugin
, @typescript-eslint/parser
).devcontainer/docker-compose.yml
docker-compose.yml
.devcontainer/Dockerfile
mcr.microsoft.com/vscode/devcontainers/typescript-node 18
apps/Dockerfile
node 20-buster-slim
backend/Dockerfile
node 20
.github/workflows/release.yml
changesets/action v1
.github/workflows/tests.yml
actions/checkout v3
apps/ks-frontend-demo/package.json
@apollo/client ^3.7.12
@babel/core ^7.21.4
@babel/plugin-proposal-class-properties ^7.18.6
@babel/plugin-proposal-object-rest-spread ^7.20.7
@babel/plugin-syntax-dynamic-import ^7.8.3
@babel/plugin-transform-runtime ^7.21.4
@babel/preset-env ^7.21.5
@babel/preset-react ^7.18.6
@babel/preset-typescript ^7.21.4
@babel/runtime ^7.21.0
@babel/runtime-corejs3 ^7.21.0
@next/bundle-analyzer ^13.4.2
@preconstruct/next ^4.0.0
core-js ^3.23.5
date-fns ^2.30.0
deepmerge ^4.3.1
downshift ^6.1.12
eslint-config-next ^13.4.2
graphql ^16.6.0
graphql-tag ^2.12.6
graphql-upload ^12.0.0
lodash ^4.17.21
lodash.debounce ^4.0.8
next ^13.4.2
next-auth ^4.22.1
nprogress ^0.2.0
prop-types ^15.8.1
react ^18.2.0
react-bootstrap ^2.7.3
react-dom ^18.2.0
react-transition-group ^4.4.5
styled-components ^5.3.9
typescript ^5.0.4
waait ^1.0.5
@apollo/react-testing ^4.0.0
@next/eslint-plugin-next ^13.4.2
@testing-library/jest-dom ^5.16.5
@testing-library/react ^11.2.7
@testing-library/user-event ^12.8.3
@types/nprogress ^0.2.0
@types/styled-components ^5.1.26
babel-eslint ^10.1.0
babel-jest ^28.1.3
babel-plugin-styled-components ^1.13.3
casual ^1.6.2
eslint ^8.40.0
eslint-config-airbnb ^19.0.4
eslint-config-prettier ^6.15.0
eslint-config-wesbos ^3.2.3
eslint-plugin-html ^6.2.0
eslint-plugin-jsx-a11y ^6.7.1
eslint-plugin-prettier ^4.2.1
eslint-plugin-react ^7.32.2
eslint-plugin-react-hooks ^4.6.0
jest ^28.1.3
prettier ^2.8.7
react-test-renderer ^18.2.0
backend/package.json
@keystone-6/core ^5.2.0
@keystone-6/fields-document ^8.0.0
@keystone-ui/button ^7.0.2
@keystone-ui/core ^5.0.2
@types/ejs ^3.1.2
dotenv ^16.0.3
ejs ^3.1.9
react ^18.2.0
typescript ^5.0.4
package.json
@babel/core ^7.21.4
@babel/eslint-parser ^7.21.8
@babel/plugin-proposal-class-properties ^7.18.6
@babel/plugin-proposal-object-rest-spread ^7.20.7
@babel/plugin-syntax-dynamic-import ^7.8.3
@babel/plugin-transform-runtime ^7.21.4
@babel/plugin-transform-typescript ^7.21.3
@babel/preset-env ^7.21.5
@babel/preset-flow ^7.21.4
@babel/preset-react ^7.18.6
@babel/preset-typescript ^7.21.4
@changesets/changelog-github ^0.4.8
@changesets/cli ^2.26.1
@manypkg/cli ^0.20.0
@preconstruct/cli 2.6.2
@preconstruct/eslint-plugin-format-js-tag ^0.2.0
@types/node ^18.16.6
@types/react ^18.2.6
@typescript-eslint/eslint-plugin ^5.53.0
@typescript-eslint/parser ^5.53.0
babel-loader ^8.3.0
babel-plugin-styled-components ^1.13.3
chalk-cli ^5.0.1
concurrently ^8.0.1
cross-env ^7.0.3
eslint ^8.40.0
eslint-plugin-cypress ^2.12.1
eslint-plugin-import ^2.27.5
eslint-plugin-jest ^27.2.1
eslint-plugin-react ^7.32.2
eslint-plugin-react-hooks ^4.6.0
is-ci ^3.0.1
prettier ^2.8.7
rimraf ^3.0.2
terminal-link-cli ^3.0.0
typescript ^5.0.4
node ^14.15.0 || ^16.13.0 || ^18.0.0
yarn 1.22.19
packages/keystone-nextjs-auth/package.json
@babel/runtime ^7.21.0
@babel/runtime-corejs3 ^7.21.0
@types/ejs ^3.1.2
cookie ^0.5.0
cross-fetch ^3.1.5
ejs ^3.1.9
fast-deep-equal ^3.1.3
next-auth ^4.22.1
@keystone-6/core ^5.2.0
react ^18.2.0
@keystone-6/core ^5.2.0
react ^18.2.0
I see in the access.ts file, the session appears to have a role
property as part of it's data. I don't have that data available within my session.
Hi there and thank you for creating and maintaining this bodacious library!
We have been building out an API using KS and so far have been very happy and impressed with it. Whilst we are using the admin UI we also have a mobile app that we are building using React Native to call KS's GraphQL API. So far so good because we have everything public, but we want to start implementing authentication/authorisation via social login providers. This library appears to offer what we need but I am unsure at this stage whether we can use it to implement social authentication via our React Native app? Are you able to indicate whether this is possible or if we need to be taking a different approach?
Thank you :-)
Ollie.
When clicking signout in the admin UI it does not clear the next-authjs session cookie.
It is possible to add an adapter to Keystone-next-auth? The email provider requires an adapter for the database.
[next-auth][error][EMAIL_REQUIRES_ADAPTER_ERROR]
https://next-auth.js.org/errors#email_requires_adapter_error E-mail login requires an adapter. MissingAdapter [MissingAdapterError]: E-mail login requires an adapter.
Documentation provides the following for Prisma:
import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client"
export default NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
...
],
})
Hi Guys,
Amazing work you've done here this project of yours has really helped me,
I'm currently implementing Auth via the google identity platform, and I'm sure I could probably implement something directly with firebase but would love to keep using this module, the only thing really stopping me is adapters aren't implemented,
https://next-auth.js.org/adapters/overview
https://next-auth.js.org/adapters/firebase
Probably just need to add the property definition "adaptor" to the AuthConfig type def, although not sure how the other dependencies might work
Keystone.ts would then look something like this
const auth = createAuth({
listKey: 'User',
identityField: 'subjectId',
sessionData: `id name email`,
autoCreate: true,
resolver: async ({user, profile, account}) => {
const username = user.name as string;
const email = user.email as string;
return { email, username };
},
keystonePath: '/admin',
sessionSecret,
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_ID || "Google Cloud Client ID",
clientSecret: process.env.GOOGLE_SECRET || "Google Cloud Client Secret",
}),
],
adapter: FirestoreAdapter({
apiKey: process.env.FIREBASE_API_KEY,
appId: process.env.FIREBASE_APP_ID,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
// Optional emulator config (see below for options)
emulator: {},
}),
});
Much love
Juan H
I followed the installation instructions and generated a vanilla keystone app.
When I run yarn dev
I get the following output
[next-auth][error][CLIENT_FETCH_ERROR]
https://next-auth.js.org/errors#client_fetch_error invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0 {
error: {
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0',
stack: 'FetchError: invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0\n' +
' at /Users/user/keystone-nextjs-auth/node_modules/next/dist/compiled/node-fetch/index.js:1:49606\n' +
' at runMicrotasks (<anonymous>)\n' +
' at processTicksAndRejections (node:internal/process/task_queues:96:5)',
name: 'FetchError'
},
path: 'session',
header: {
'x-forwarded-host': 'localhost:3000',
'x-forwarded-proto': 'http',
'x-forwarded-port': '3000',
'x-forwarded-for': '::ffff:127.0.0.1',
connection: 'close',
host: 'localhost:3000',
'accept-encoding': 'gzip,deflate',
'user-agent': 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)',
accept: '*/*'
},
message: 'invalid json response body at http://localhost:3000/api/auth/session reason: Unexpected token < in JSON at position 0'
This log is being printed continuously.
I also tried checking out the original source code and ran yarn dev
in the backend
folder (setting my auth0 creds as env vars) and I get the same problem.
In this file line 96 I see a piece of code that is commented out. As I've understood this is planned for autoUpdate
option ;)
That would be really great to have this option, I can also contribute if needed.
Thank you for working on this great addition to Keystone!
I want to enable both Keystone's built-in auth (https://keystonejs.com/docs/apis/auth) and a social auth for my project. Will this package do both, or do I have to implement the built-in auth separately?
Hi, I am using your backend example, and there is something that is not clear to me... I expected it to load into session all permission assigned to the user's role.. but when I look at the session object I see only id, name, email.
I believe this is because of this line https://github.com/OpenSaasAU/keystone-nextjs-auth/blob/main/backend/keystone.ts#L25
If I change in keystone.ts :
import { permissionsList } from './schemas/permissionFields';
...
sessionData: `id name email role {${permissionsList.join(' ')}}`
then everything works!
Hey mate thanks again for putting this together 👌
I'm keen to have something similar to @keystone-next/auth
's initFirstItem
->data
to populate other fields on the first User record.
Right now, using this package, that logic needs to be put in a hook. Which is actually fine right now, but the offering from Keystone raised the initial user as a priority in the design of their Authentication Config API so perhaps its a good idea to follow that here too.
Would you be up for (me) adding that here?
As an approach to add this to the Config API, I was thinking it'd be good to follow the style of initFirstItem
. This would be a breaking change though:
// An example User list with an additional 'role' field.
const User = list({
fields: {
name: text({ isRequired: true }),
email: text({ isRequired: true, isUnique: true }),
subjectId: text({ isUnique: true }),
// We may want to initialise this differently for the first User.
role: select({ defaultValue: 'USER', options: [ { value: 'USER' }, { value: 'MODERATOR' }, { value: 'ADMIN' } ] }),
},
});
const auth = createAuth({
listKey: 'User',
identityField: 'subjectId',
sessionData: `id name email`,
initFirstItem: {
// 1. Moving the mappings into "initFirstItem" object makes sense, IMO! They're only ever used when creating a new User.
// 2. Reshaping it like this *may* also be a good move, to add explicitness to the Config API.
mapFieldsFromAuthArgs: {
user: { subjectId: 'id', name: 'name' },
account: {},
profile: { email: 'email' },
},
data: {
// Let's make the first user an "ADMIN" instead of the default "USER" role.
role: 'ADMIN'
}
});
Hi, I have completed a test integration with Keycloak as identity provider using your backend example. Everything works fine except for the logout function. Here's how I reproduce the problem:
If I check in Keycloak I can see the user's session is still active. I think there should be a way for keystone to signal to keycloak that the user has ended their session. I know the .well-known file exposes a end_session_endpoint, I am wondering if this should be used somehow.
TIA
First of all thank you for the effort you put in to make this package.
I was wondering what it would take to integrate this with Keystone Auth
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.